; 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 %A, ptr %upper) {
; CHECK-LABEL: @gep_constant_positive_index(
; CHECK-NEXT: [[ADD_I8_4:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 4
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[ADD_I16_4:%.*]] = getelementptr inbounds i16, ptr [[A]], i64 4
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I16_4]], [[UPPER]]
; CHECK-NEXT: [[ADD_I16_2:%.*]] = getelementptr inbounds i16, ptr [[A]], i64 2
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true
; CHECK-NEXT: ret i1 [[RES_1]]
;
%add.i8.4 = getelementptr inbounds i8, ptr %A, i64 4
%c.0 = icmp ult ptr %add.i8.4, %upper
call void @llvm.assume(i1 %c.0)
%add.i16.4 = getelementptr inbounds i16, ptr %A, i64 4
%c.1 = icmp ult ptr %add.i16.4, %upper
%add.i16.2 = getelementptr inbounds i16, ptr %A, i64 2
%t.1 = icmp ult ptr %add.i16.2, %upper
%res.1 = xor i1 %c.1, %t.1
ret i1 %res.1
}
define i1 @gep_constant_positive_index_chained(ptr %A, ptr %upper) {
; CHECK-LABEL: @gep_constant_positive_index_chained(
; CHECK-NEXT: [[ADD_I8_4:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 4
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[ADD_I8_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 1
; CHECK-NEXT: [[ADD_I16_1:%.*]] = getelementptr inbounds i16, ptr [[ADD_I8_1]], i64 1
; CHECK-NEXT: [[ADD_I16_2:%.*]] = getelementptr inbounds i16, ptr [[ADD_I8_1]], i64 2
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I16_2]], [[UPPER]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, [[C_1]]
; CHECK-NEXT: ret i1 [[RES_1]]
;
%add.i8.4 = getelementptr inbounds i8, ptr %A, i64 4
%c.0 = icmp ult ptr %add.i8.4, %upper
call void @llvm.assume(i1 %c.0)
%add.i8.1 = getelementptr inbounds i8, ptr %A, i64 1
%add.i16.1 = getelementptr inbounds i16, ptr %add.i8.1, i64 1
%t.1 = icmp ult ptr %add.i16.1, %upper
%add.i16.2 = getelementptr inbounds i16, ptr %add.i8.1, i64 2
%c.1 = icmp ult ptr %add.i16.2, %upper
%res.1 = xor i1 %t.1, %c.1
ret i1 %res.1
}
define i1 @gep_var_positive_index(ptr %A, ptr %upper, i8 %idx) {
; CHECK-LABEL: @gep_var_positive_index(
; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_POS]])
; CHECK-NEXT: [[ADD_I16_IDX:%.*]] = getelementptr inbounds i16, ptr [[A:%.*]], i8 [[IDX]]
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I16_IDX]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[ADD_I32_IDX:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX]], [[UPPER]]
; CHECK-NEXT: [[ADD_I8_IDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true
; CHECK-NEXT: ret i1 [[RES_1]]
;
%idx.pos = icmp sge i8 %idx, 0
call void @llvm.assume(i1 %idx.pos)
%add.i16.idx = getelementptr inbounds i16, ptr %A, i8 %idx
%c.0 = icmp ult ptr %add.i16.idx, %upper
call void @llvm.assume(i1 %c.0)
%add.i32.idx = getelementptr inbounds i32, ptr %A, i8 %idx
%c.1 = icmp ult ptr %add.i32.idx, %upper
%add.i8.idx = getelementptr inbounds i8, ptr %A, i8 %idx
%t.1 = icmp ult ptr %add.i8.idx, %upper
%res.1 = xor i1 %c.1, %t.1
ret i1 %res.1
}
define i1 @gep_add_nsw_positive_index(ptr %A, ptr %upper, i8 %idx) {
; CHECK-LABEL: @gep_add_nsw_positive_index(
; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_POS]])
; CHECK-NEXT: [[IDX_3:%.*]] = add nsw i8 [[IDX]], 3
; CHECK-NEXT: [[ADD_I8_IDX_3:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i8 [[IDX_3]]
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_3]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[IDX_1:%.*]] = add nsw i8 [[IDX]], 1
; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_1]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX_1]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true
; CHECK-NEXT: [[ADD_I16_IDX_1:%.*]] = getelementptr inbounds i16, ptr [[A]], i8 [[IDX_1]]
; CHECK-NEXT: [[C_2:%.*]] = icmp ult ptr [[ADD_I16_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_2]]
; CHECK-NEXT: ret i1 [[RES_2]]
;
%idx.pos = icmp sge i8 %idx, 0
call void @llvm.assume(i1 %idx.pos)
%idx.3 = add nsw i8 %idx, 3
%add.i8.idx.3 = getelementptr inbounds i8, ptr %A, i8 %idx.3
%c.0 = icmp ult ptr %add.i8.idx.3, %upper
call void @llvm.assume(i1 %c.0)
%idx.1 = add nsw i8 %idx, 1
%add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i8 %idx.1
%c.1 = icmp ult ptr %add.i32.idx.1, %upper
%add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i8 %idx.1
%t.1 = icmp ult ptr %add.i8.idx.1, %upper
%res.1 = xor i1 %c.1, %t.1
%add.i16.idx.1 = getelementptr inbounds i16, ptr %A, i8 %idx.1
%c.2 = icmp ult ptr %add.i16.idx.1, %upper
%res.2 = xor i1 %res.1, %c.2
ret i1 %res.2
}
define i1 @gep_shl_nsw_positive_index(ptr %A, ptr %upper, i8 %idx) {
; CHECK-LABEL: @gep_shl_nsw_positive_index(
; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_POS]])
; CHECK-NEXT: [[IDX_2:%.*]] = shl nsw i8 [[IDX]], 2
; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i8 [[IDX_2]]
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[IDX_1:%.*]] = shl nsw i8 [[IDX]], 1
; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_1]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX_1]]
; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[ADD_I8_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]]
; CHECK-NEXT: ret i1 [[RES_1]]
;
%idx.pos = icmp sge i8 %idx, 0
call void @llvm.assume(i1 %idx.pos)
%idx.2 = shl nsw i8 %idx, 2
%add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i8 %idx.2
%c.0 = icmp ult ptr %add.i8.idx.2, %upper
call void @llvm.assume(i1 %c.0)
%idx.1 = shl nsw i8 %idx, 1
%add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i8 %idx.1
%c.1 = icmp ult ptr %add.i32.idx.1, %upper
%add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i8 %idx.1
%t.1 = icmp ult ptr %add.i8.idx.1, %upper
%res.1 = xor i1 %c.1, %t.1
ret i1 %res.1
}
define i1 @gep_zext_add_nuw_nsw_index(ptr %A, ptr %upper, i8 %idx) {
; CHECK-LABEL: @gep_zext_add_nuw_nsw_index(
; CHECK-NEXT: [[IDX_3:%.*]] = add nuw nsw i8 [[IDX:%.*]], 3
; CHECK-NEXT: [[IDX_3_EXT:%.*]] = zext i8 [[IDX_3]] to i16
; CHECK-NEXT: [[ADD_I8_IDX_3:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_3_EXT]]
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_3]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[IDX_1:%.*]] = add nuw nsw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true
; CHECK-NEXT: [[ADD_I16_IDX_1:%.*]] = getelementptr inbounds i16, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[C_2:%.*]] = icmp ult ptr [[ADD_I16_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_2]]
; CHECK-NEXT: ret i1 [[RES_2]]
;
%idx.3 = add nuw nsw i8 %idx, 3
%idx.3.ext = zext i8 %idx.3 to i16
%add.i8.idx.3 = getelementptr inbounds i8, ptr %A, i16 %idx.3.ext
%c.0 = icmp ult ptr %add.i8.idx.3, %upper
call void @llvm.assume(i1 %c.0)
%idx.1 = add nuw nsw i8 %idx, 1
%idx.1.ext = zext i8 %idx.1 to i16
%add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
%c.1 = icmp ult ptr %add.i32.idx.1, %upper
%add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
%t.1 = icmp ult ptr %add.i8.idx.1, %upper
%res.1 = xor i1 %c.1, %t.1
%add.i16.idx.1 = getelementptr inbounds i16, ptr %A, i16 %idx.1.ext
%c.2 = icmp ult ptr %add.i16.idx.1, %upper
%res.2 = xor i1 %res.1, %c.2
ret i1 %res.2
}
define i1 @gep_zext_add_nuw_index(ptr %A, ptr %upper, i8 %idx) {
; CHECK-LABEL: @gep_zext_add_nuw_index(
; CHECK-NEXT: [[IDX_2:%.*]] = add nuw i8 [[IDX:%.*]], 2
; CHECK-NEXT: [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16
; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]]
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[IDX_1:%.*]] = add nuw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true
; CHECK-NEXT: ret i1 [[RES_1]]
;
%idx.2 = add nuw i8 %idx, 2
%idx.2.ext = zext i8 %idx.2 to i16
%add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext
%c.0 = icmp ult ptr %add.i8.idx.2, %upper
call void @llvm.assume(i1 %c.0)
%idx.1 = add nuw i8 %idx, 1
%idx.1.ext = zext i8 %idx.1 to i16
%add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
%c.1 = icmp ult ptr %add.i32.idx.1, %upper
%add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
%t.1 = icmp ult ptr %add.i8.idx.1, %upper
%res.1 = xor i1 %c.1, %t.1
ret i1 %res.1
}
define i1 @gep_zext_add_nsw_index(ptr %A, ptr %upper, i8 %idx) {
; CHECK-LABEL: @gep_zext_add_nsw_index(
; CHECK-NEXT: [[IDX_2:%.*]] = add nsw i8 [[IDX:%.*]], 2
; CHECK-NEXT: [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16
; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]]
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[IDX_1:%.*]] = add nsw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[ADD_I8_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]]
; CHECK-NEXT: ret i1 [[RES_1]]
;
%idx.2 = add nsw i8 %idx, 2
%idx.2.ext = zext i8 %idx.2 to i16
%add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext
%c.0 = icmp ult ptr %add.i8.idx.2, %upper
call void @llvm.assume(i1 %c.0)
%idx.1 = add nsw i8 %idx, 1
%idx.1.ext = zext i8 %idx.1 to i16
%add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
%c.1 = icmp ult ptr %add.i32.idx.1, %upper
%add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
%t.1 = icmp ult ptr %add.i8.idx.1, %upper
%res.1 = xor i1 %c.1, %t.1
ret i1 %res.1
}
define i1 @gep_zext_index(ptr %A, ptr %upper, i8 %idx.1, i8 %idx.2) {
; CHECK-LABEL: @gep_zext_index(
; CHECK-NEXT: [[C_0:%.*]] = icmp ult i8 [[IDX_1:%.*]], [[IDX_2:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16
; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]]
; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[ADD_I8_IDX_2]]
; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true
; CHECK-NEXT: ret i1 [[RES_1]]
;
%c.0 = icmp ult i8 %idx.1, %idx.2
call void @llvm.assume(i1 %c.0)
%idx.2.ext = zext i8 %idx.2 to i16
%add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext
%idx.1.ext = zext i8 %idx.1 to i16
%add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
%c.1 = icmp ult ptr %add.i32.idx.1, %add.i8.idx.2
%add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
%t.1 = icmp ult ptr %add.i8.idx.1, %add.i8.idx.2
%res.1 = xor i1 %c.1, %t.1
ret i1 %res.1
}
define i1 @gep_zext_shl_nsw_index(ptr %A, ptr %upper, i8 %idx) {
; CHECK-LABEL: @gep_zext_shl_nsw_index(
; CHECK-NEXT: [[IDX_2:%.*]] = shl nsw i8 [[IDX:%.*]], 2
; CHECK-NEXT: [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16
; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]]
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[IDX_1:%.*]] = shl nsw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[ADD_I8_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]]
; CHECK-NEXT: ret i1 [[RES_1]]
;
%idx.2 = shl nsw i8 %idx, 2
%idx.2.ext = zext i8 %idx.2 to i16
%add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext
%c.0 = icmp ult ptr %add.i8.idx.2, %upper
call void @llvm.assume(i1 %c.0)
%idx.1 = shl nsw i8 %idx, 1
%idx.1.ext = zext i8 %idx.1 to i16
%add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
%c.1 = icmp ult ptr %add.i32.idx.1, %upper
%add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
%t.1 = icmp ult ptr %add.i8.idx.1, %upper
%res.1 = xor i1 %c.1, %t.1
ret i1 %res.1
}
define i1 @gep_zext_shl_nuw_index(ptr %A, ptr %upper, i8 %idx) {
; CHECK-LABEL: @gep_zext_shl_nuw_index(
; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sgt i8 [[IDX:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_POS]])
; CHECK-NEXT: [[IDX_2:%.*]] = shl nuw i8 [[IDX]], 2
; CHECK-NEXT: [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16
; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]]
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[IDX_1:%.*]] = shl nuw i8 [[IDX]], 1
; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16
; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true
; CHECK-NEXT: ret i1 [[RES_1]]
;
%idx.pos = icmp sgt i8 %idx, 0
call void @llvm.assume(i1 %idx.pos)
%idx.2 = shl nuw i8 %idx, 2
%idx.2.ext = zext i8 %idx.2 to i16
%add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext
%c.0 = icmp ult ptr %add.i8.idx.2, %upper
call void @llvm.assume(i1 %c.0)
%idx.1 = shl nuw i8 %idx, 1
%idx.1.ext = zext i8 %idx.1 to i16
%add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext
%c.1 = icmp ult ptr %add.i32.idx.1, %upper
%add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext
%t.1 = icmp ult ptr %add.i8.idx.1, %upper
%res.1 = xor i1 %c.1, %t.1
ret i1 %res.1
}
%struct.t = type { i8, i8 }
define i1 @gep_add_nsw_positive_index_struct(ptr %A, ptr %upper, i8 %idx) {
; CHECK-LABEL: @gep_add_nsw_positive_index_struct(
; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_POS]])
; CHECK-NEXT: [[IDX_3:%.*]] = add nsw i8 [[IDX]], 2
; CHECK-NEXT: [[ADD_I8_IDX_3:%.*]] = getelementptr inbounds [[STRUCT_T:%.*]], ptr [[A:%.*]], i8 [[IDX_3]]
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_3]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[IDX_1:%.*]] = add nsw i8 [[IDX]], 1
; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_1]]
; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX_1]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], true
; CHECK-NEXT: [[ADD_I16_IDX_1:%.*]] = getelementptr inbounds i16, ptr [[A]], i8 [[IDX_1]]
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], true
; CHECK-NEXT: [[ADD_I64_IDX_1:%.*]] = getelementptr inbounds i64, ptr [[A]], i8 [[IDX_1]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I64_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[RES_2]], [[C_1]]
; CHECK-NEXT: ret i1 [[RES_3]]
;
%idx.pos = icmp sge i8 %idx, 0
call void @llvm.assume(i1 %idx.pos)
%idx.3 = add nsw i8 %idx, 2
%add.i8.idx.3 = getelementptr inbounds %struct.t, ptr %A, i8 %idx.3
%c.0 = icmp ult ptr %add.i8.idx.3, %upper
call void @llvm.assume(i1 %c.0)
%idx.1 = add nsw i8 %idx, 1
%add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i8 %idx.1
%t.1 = icmp ult ptr %add.i32.idx.1, %upper
%add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i8 %idx.1
%t.2 = icmp ult ptr %add.i8.idx.1, %upper
%res.1 = xor i1 %t.1, %t.2
%add.i16.idx.1 = getelementptr inbounds i16, ptr %A, i8 %idx.1
%t.3 = icmp ult ptr %add.i16.idx.1, %upper
%res.2 = xor i1 %res.1, %t.3
%add.i64.idx.1 = getelementptr inbounds i64, ptr %A, i8 %idx.1
%c.1 = icmp ult ptr %add.i64.idx.1, %upper
%res.3 = xor i1 %res.2, %c.1
ret i1 %res.3
}
define i1 @gep_constant_positive_index_fixed_vector_ty(ptr %A, ptr %upper) {
; CHECK-LABEL: @gep_constant_positive_index_fixed_vector_ty(
; CHECK-NEXT: [[ADD_I8_4:%.*]] = getelementptr inbounds <4 x i8>, ptr [[A:%.*]], i64 4
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[ADD_I16_4:%.*]] = getelementptr inbounds <4 x i16>, ptr [[A]], i64 4
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I16_4]], [[UPPER]]
; CHECK-NEXT: [[ADD_I16_2:%.*]] = getelementptr inbounds <4 x i16>, ptr [[A]], i64 2
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true
; CHECK-NEXT: ret i1 [[RES_1]]
;
%add.i8.4 = getelementptr inbounds <4 x i8>, ptr %A, i64 4
%c.0 = icmp ult ptr %add.i8.4, %upper
call void @llvm.assume(i1 %c.0)
%add.i16.4 = getelementptr inbounds <4 x i16>, ptr %A, i64 4
%c.1 = icmp ult ptr %add.i16.4, %upper
%add.i16.2 = getelementptr inbounds <4 x i16>, ptr %A, i64 2
%t.1 = icmp ult ptr %add.i16.2, %upper
%res.1 = xor i1 %c.1, %t.1
ret i1 %res.1
}
define i1 @gep_constant_positive_index_scalable_vector_ty(ptr %A, ptr %upper) {
; CHECK-LABEL: @gep_constant_positive_index_scalable_vector_ty(
; CHECK-NEXT: [[ADD_I8_4:%.*]] = getelementptr inbounds <vscale x 4 x i8>, ptr [[A:%.*]], i64 4
; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]])
; CHECK-NEXT: [[ADD_I16_4:%.*]] = getelementptr inbounds <vscale x 4 x i16>, ptr [[A]], i64 4
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I16_4]], [[UPPER]]
; CHECK-NEXT: [[ADD_I16_2:%.*]] = getelementptr inbounds <vscale x 4 x i16>, ptr [[A]], i64 2
; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[ADD_I16_2]], [[UPPER]]
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]]
; CHECK-NEXT: ret i1 [[RES_1]]
;
%add.i8.4 = getelementptr inbounds <vscale x 4 x i8>, ptr %A, i64 4
%c.0 = icmp ult ptr %add.i8.4, %upper
call void @llvm.assume(i1 %c.0)
%add.i16.4 = getelementptr inbounds <vscale x 4 x i16>, ptr %A, i64 4
%c.1 = icmp ult ptr %add.i16.4, %upper
%add.i16.2 = getelementptr inbounds <vscale x 4 x i16>, ptr %A, i64 2
%t.1 = icmp ult ptr %add.i16.2, %upper
%res.1 = xor i1 %c.1, %t.1
ret i1 %res.1
}