When the sub arguments are ptr2int it is not possible to determine computeKnownBits() of its arguments. For scalar case generally sub of 2 ptr2int are converted to sub of indexes. However a loop with recursive GEP/PHI where the arguments to sub is of type ptr2int, if it is possible to determine that a sub of this GEP and another pointer with the same base is KnownNonZero we can return this. This helps subsequent passes to optimize the loop further.
534 lines
18 KiB
LLVM
534 lines
18 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
|
|
|
|
target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
|
|
|
|
define i64 @test_inbounds(ptr %base, i64 %idx) {
|
|
; CHECK-LABEL: @test_inbounds(
|
|
; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 2
|
|
; CHECK-NEXT: ret i64 [[P2_IDX]]
|
|
;
|
|
%p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%i1 = ptrtoint ptr %base to i64
|
|
%i2 = ptrtoint ptr %p2 to i64
|
|
%d = sub i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
define i64 @test_partial_inbounds1(ptr %base, i64 %idx) {
|
|
; CHECK-LABEL: @test_partial_inbounds1(
|
|
; CHECK-NEXT: [[P2_IDX:%.*]] = shl i64 [[IDX:%.*]], 2
|
|
; CHECK-NEXT: ret i64 [[P2_IDX]]
|
|
;
|
|
%p2 = getelementptr [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%i1 = ptrtoint ptr %base to i64
|
|
%i2 = ptrtoint ptr %p2 to i64
|
|
%d = sub i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
define i64 @test_partial_inbounds2(ptr %base, i64 %idx) {
|
|
; CHECK-LABEL: @test_partial_inbounds2(
|
|
; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 2
|
|
; CHECK-NEXT: ret i64 [[P2_IDX]]
|
|
;
|
|
%p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%i1 = ptrtoint ptr %base to i64
|
|
%i2 = ptrtoint ptr %p2 to i64
|
|
%d = sub i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
define i64 @test_inbounds_nuw(ptr %base, i64 %idx) {
|
|
; CHECK-LABEL: @test_inbounds_nuw(
|
|
; CHECK-NEXT: [[P2_IDX:%.*]] = shl nuw nsw i64 [[IDX:%.*]], 2
|
|
; CHECK-NEXT: ret i64 [[P2_IDX]]
|
|
;
|
|
%p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%i1 = ptrtoint ptr %base to i64
|
|
%i2 = ptrtoint ptr %p2 to i64
|
|
%d = sub nuw i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
define i64 @test_nuw(ptr %base, i64 %idx) {
|
|
; CHECK-LABEL: @test_nuw(
|
|
; CHECK-NEXT: [[P2_IDX:%.*]] = shl i64 [[IDX:%.*]], 2
|
|
; CHECK-NEXT: ret i64 [[P2_IDX]]
|
|
;
|
|
%p2 = getelementptr [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%i1 = ptrtoint ptr %base to i64
|
|
%i2 = ptrtoint ptr %p2 to i64
|
|
%d = sub nuw i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
define i32 @test_inbounds_nuw_trunc(ptr %base, i64 %idx) {
|
|
; CHECK-LABEL: @test_inbounds_nuw_trunc(
|
|
; CHECK-NEXT: [[IDX_TR:%.*]] = trunc i64 [[IDX:%.*]] to i32
|
|
; CHECK-NEXT: [[D:%.*]] = shl i32 [[IDX_TR]], 2
|
|
; CHECK-NEXT: ret i32 [[D]]
|
|
;
|
|
%p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%i1 = ptrtoint ptr %base to i64
|
|
%i2 = ptrtoint ptr %p2 to i64
|
|
%t1 = trunc i64 %i1 to i32
|
|
%t2 = trunc i64 %i2 to i32
|
|
%d = sub nuw i32 %t2, %t1
|
|
ret i32 %d
|
|
}
|
|
|
|
define i64 @test_inbounds_nuw_swapped(ptr %base, i64 %idx) {
|
|
; CHECK-LABEL: @test_inbounds_nuw_swapped(
|
|
; CHECK-NEXT: [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4
|
|
; CHECK-NEXT: ret i64 [[P2_IDX_NEG]]
|
|
;
|
|
%p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%i1 = ptrtoint ptr %p2 to i64
|
|
%i2 = ptrtoint ptr %base to i64
|
|
%d = sub nuw i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
define i64 @test_inbounds1_nuw_swapped(ptr %base, i64 %idx) {
|
|
; CHECK-LABEL: @test_inbounds1_nuw_swapped(
|
|
; CHECK-NEXT: [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4
|
|
; CHECK-NEXT: ret i64 [[P2_IDX_NEG]]
|
|
;
|
|
%p2 = getelementptr [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%i1 = ptrtoint ptr %p2 to i64
|
|
%i2 = ptrtoint ptr %base to i64
|
|
%d = sub nuw i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
define i64 @test_inbounds2_nuw_swapped(ptr %base, i64 %idx) {
|
|
; CHECK-LABEL: @test_inbounds2_nuw_swapped(
|
|
; CHECK-NEXT: [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4
|
|
; CHECK-NEXT: ret i64 [[P2_IDX_NEG]]
|
|
;
|
|
%p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%i1 = ptrtoint ptr %p2 to i64
|
|
%i2 = ptrtoint ptr %base to i64
|
|
%d = sub nuw i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
define i64 @test_inbounds_two_gep(ptr %base, i64 %idx, i64 %idx2) {
|
|
; CHECK-LABEL: @test_inbounds_two_gep(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]]
|
|
; CHECK-NEXT: [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2
|
|
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
|
;
|
|
%p1 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx2
|
|
%i1 = ptrtoint ptr %p1 to i64
|
|
%i2 = ptrtoint ptr %p2 to i64
|
|
%d = sub i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
define i64 @test_inbounds_nsw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
|
|
; CHECK-LABEL: @test_inbounds_nsw_two_gep(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]]
|
|
; CHECK-NEXT: [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2
|
|
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
|
;
|
|
%p1 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx2
|
|
%i1 = ptrtoint ptr %p1 to i64
|
|
%i2 = ptrtoint ptr %p2 to i64
|
|
%d = sub nsw i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
define i64 @test_inbounds_nuw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
|
|
; CHECK-LABEL: @test_inbounds_nuw_two_gep(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]]
|
|
; CHECK-NEXT: [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2
|
|
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
|
;
|
|
%p1 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
|
|
%p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx2
|
|
%i1 = ptrtoint ptr %p1 to i64
|
|
%i2 = ptrtoint ptr %p2 to i64
|
|
%d = sub nuw i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
define i64 @test_inbounds_nuw_multi_index(ptr %base, i64 %idx, i64 %idx2) {
|
|
; CHECK-LABEL: @test_inbounds_nuw_multi_index(
|
|
; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 3
|
|
; CHECK-NEXT: [[P2_IDX1:%.*]] = shl nsw i64 [[IDX2:%.*]], 2
|
|
; CHECK-NEXT: [[P2_OFFS:%.*]] = add nsw i64 [[P2_IDX]], [[P2_IDX1]]
|
|
; CHECK-NEXT: ret i64 [[P2_OFFS]]
|
|
;
|
|
%p2 = getelementptr inbounds [0 x [2 x i32]], ptr %base, i64 0, i64 %idx, i64 %idx2
|
|
%i1 = ptrtoint ptr %base to i64
|
|
%i2 = ptrtoint ptr %p2 to i64
|
|
%d = sub nuw i64 %i2, %i1
|
|
ret i64 %d
|
|
}
|
|
|
|
; rdar://7362831
|
|
define i32 @test23(ptr %P, i64 %A){
|
|
; CHECK-LABEL: @test23(
|
|
; CHECK-NEXT: [[G:%.*]] = trunc i64 [[A:%.*]] to i32
|
|
; CHECK-NEXT: ret i32 [[G]]
|
|
;
|
|
%B = getelementptr inbounds i8, ptr %P, i64 %A
|
|
%C = ptrtoint ptr %B to i64
|
|
%D = trunc i64 %C to i32
|
|
%E = ptrtoint ptr %P to i64
|
|
%F = trunc i64 %E to i32
|
|
%G = sub i32 %D, %F
|
|
ret i32 %G
|
|
}
|
|
|
|
define i8 @test23_as1(ptr addrspace(1) %P, i16 %A) {
|
|
; CHECK-LABEL: @test23_as1(
|
|
; CHECK-NEXT: [[G:%.*]] = trunc i16 [[A:%.*]] to i8
|
|
; CHECK-NEXT: ret i8 [[G]]
|
|
;
|
|
%B = getelementptr inbounds i8, ptr addrspace(1) %P, i16 %A
|
|
%C = ptrtoint ptr addrspace(1) %B to i16
|
|
%D = trunc i16 %C to i8
|
|
%E = ptrtoint ptr addrspace(1) %P to i16
|
|
%F = trunc i16 %E to i8
|
|
%G = sub i8 %D, %F
|
|
ret i8 %G
|
|
}
|
|
|
|
define i64 @test24(ptr %P, i64 %A){
|
|
; CHECK-LABEL: @test24(
|
|
; CHECK-NEXT: ret i64 [[A:%.*]]
|
|
;
|
|
%B = getelementptr inbounds i8, ptr %P, i64 %A
|
|
%C = ptrtoint ptr %B to i64
|
|
%E = ptrtoint ptr %P to i64
|
|
%G = sub i64 %C, %E
|
|
ret i64 %G
|
|
}
|
|
|
|
define i16 @test24_as1(ptr addrspace(1) %P, i16 %A) {
|
|
; CHECK-LABEL: @test24_as1(
|
|
; CHECK-NEXT: ret i16 [[A:%.*]]
|
|
;
|
|
%B = getelementptr inbounds i8, ptr addrspace(1) %P, i16 %A
|
|
%C = ptrtoint ptr addrspace(1) %B to i16
|
|
%E = ptrtoint ptr addrspace(1) %P to i16
|
|
%G = sub i16 %C, %E
|
|
ret i16 %G
|
|
}
|
|
|
|
define i64 @test24a(ptr %P, i64 %A){
|
|
; CHECK-LABEL: @test24a(
|
|
; CHECK-NEXT: [[DIFF_NEG:%.*]] = sub i64 0, [[A:%.*]]
|
|
; CHECK-NEXT: ret i64 [[DIFF_NEG]]
|
|
;
|
|
%B = getelementptr inbounds i8, ptr %P, i64 %A
|
|
%C = ptrtoint ptr %B to i64
|
|
%E = ptrtoint ptr %P to i64
|
|
%G = sub i64 %E, %C
|
|
ret i64 %G
|
|
}
|
|
|
|
define i16 @test24a_as1(ptr addrspace(1) %P, i16 %A) {
|
|
; CHECK-LABEL: @test24a_as1(
|
|
; CHECK-NEXT: [[DIFF_NEG:%.*]] = sub i16 0, [[A:%.*]]
|
|
; CHECK-NEXT: ret i16 [[DIFF_NEG]]
|
|
;
|
|
%B = getelementptr inbounds i8, ptr addrspace(1) %P, i16 %A
|
|
%C = ptrtoint ptr addrspace(1) %B to i16
|
|
%E = ptrtoint ptr addrspace(1) %P to i16
|
|
%G = sub i16 %E, %C
|
|
ret i16 %G
|
|
}
|
|
|
|
@Arr = external global [42 x i16]
|
|
|
|
define i64 @test24b(ptr %P, i64 %A){
|
|
; CHECK-LABEL: @test24b(
|
|
; CHECK-NEXT: [[B_IDX:%.*]] = shl nsw i64 [[A:%.*]], 1
|
|
; CHECK-NEXT: ret i64 [[B_IDX]]
|
|
;
|
|
%B = getelementptr inbounds [42 x i16], ptr @Arr, i64 0, i64 %A
|
|
%C = ptrtoint ptr %B to i64
|
|
%G = sub i64 %C, ptrtoint (ptr @Arr to i64)
|
|
ret i64 %G
|
|
}
|
|
|
|
define i64 @test25(ptr %P, i64 %A){
|
|
; CHECK-LABEL: @test25(
|
|
; CHECK-NEXT: [[B_IDX:%.*]] = shl nsw i64 [[A:%.*]], 1
|
|
; CHECK-NEXT: [[GEPDIFF:%.*]] = add nsw i64 [[B_IDX]], -84
|
|
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
|
;
|
|
%B = getelementptr inbounds [42 x i16], ptr @Arr, i64 0, i64 %A
|
|
%C = ptrtoint ptr %B to i64
|
|
%G = sub i64 %C, ptrtoint (ptr getelementptr ([42 x i16], ptr @Arr, i64 1, i64 0) to i64)
|
|
ret i64 %G
|
|
}
|
|
|
|
@Arr_as1 = external addrspace(1) global [42 x i16]
|
|
|
|
define i16 @test25_as1(ptr addrspace(1) %P, i64 %A) {
|
|
; CHECK-LABEL: @test25_as1(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[A:%.*]] to i16
|
|
; CHECK-NEXT: [[B_IDX:%.*]] = shl nsw i16 [[TMP1]], 1
|
|
; CHECK-NEXT: [[GEPDIFF:%.*]] = add nsw i16 [[B_IDX]], -84
|
|
; CHECK-NEXT: ret i16 [[GEPDIFF]]
|
|
;
|
|
%B = getelementptr inbounds [42 x i16], ptr addrspace(1) @Arr_as1, i64 0, i64 %A
|
|
%C = ptrtoint ptr addrspace(1) %B to i16
|
|
%G = sub i16 %C, ptrtoint (ptr addrspace(1) getelementptr ([42 x i16], ptr addrspace(1) @Arr_as1, i64 1, i64 0) to i16)
|
|
ret i16 %G
|
|
}
|
|
|
|
define i64 @test30(ptr %foo, i64 %i, i64 %j) {
|
|
; CHECK-LABEL: @test30(
|
|
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
|
|
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i64 [[GEP1_IDX]], [[J:%.*]]
|
|
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
|
;
|
|
%gep1 = getelementptr inbounds i32, ptr %foo, i64 %i
|
|
%gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
|
|
%cast1 = ptrtoint ptr %gep1 to i64
|
|
%cast2 = ptrtoint ptr %gep2 to i64
|
|
%sub = sub i64 %cast1, %cast2
|
|
ret i64 %sub
|
|
}
|
|
|
|
define i16 @test30_as1(ptr addrspace(1) %foo, i16 %i, i16 %j) {
|
|
; CHECK-LABEL: @test30_as1(
|
|
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2
|
|
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i16 [[GEP1_IDX]], [[J:%.*]]
|
|
; CHECK-NEXT: ret i16 [[GEPDIFF]]
|
|
;
|
|
%gep1 = getelementptr inbounds i32, ptr addrspace(1) %foo, i16 %i
|
|
%gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i16 %j
|
|
%cast1 = ptrtoint ptr addrspace(1) %gep1 to i16
|
|
%cast2 = ptrtoint ptr addrspace(1) %gep2 to i16
|
|
%sub = sub i16 %cast1, %cast2
|
|
ret i16 %sub
|
|
}
|
|
|
|
; Inbounds translates to 'nsw' on sub
|
|
|
|
define i64 @gep_diff_both_inbounds(ptr %foo, i64 %i, i64 %j) {
|
|
; CHECK-LABEL: @gep_diff_both_inbounds(
|
|
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i64 [[I:%.*]], [[J:%.*]]
|
|
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
|
;
|
|
%gep1 = getelementptr inbounds i8, ptr %foo, i64 %i
|
|
%gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
|
|
%cast1 = ptrtoint ptr %gep1 to i64
|
|
%cast2 = ptrtoint ptr %gep2 to i64
|
|
%sub = sub i64 %cast1, %cast2
|
|
ret i64 %sub
|
|
}
|
|
|
|
; Negative test for 'nsw' - both geps must be inbounds
|
|
|
|
define i64 @gep_diff_first_inbounds(ptr %foo, i64 %i, i64 %j) {
|
|
; CHECK-LABEL: @gep_diff_first_inbounds(
|
|
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]]
|
|
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
|
;
|
|
%gep1 = getelementptr inbounds i8, ptr %foo, i64 %i
|
|
%gep2 = getelementptr i8, ptr %foo, i64 %j
|
|
%cast1 = ptrtoint ptr %gep1 to i64
|
|
%cast2 = ptrtoint ptr %gep2 to i64
|
|
%sub = sub i64 %cast1, %cast2
|
|
ret i64 %sub
|
|
}
|
|
|
|
; Negative test for 'nsw' - both geps must be inbounds
|
|
|
|
define i64 @gep_diff_second_inbounds(ptr %foo, i64 %i, i64 %j) {
|
|
; CHECK-LABEL: @gep_diff_second_inbounds(
|
|
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]]
|
|
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
|
;
|
|
%gep1 = getelementptr i8, ptr %foo, i64 %i
|
|
%gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
|
|
%cast1 = ptrtoint ptr %gep1 to i64
|
|
%cast2 = ptrtoint ptr %gep2 to i64
|
|
%sub = sub i64 %cast1, %cast2
|
|
ret i64 %sub
|
|
}
|
|
|
|
define i64 @gep_diff_with_bitcast(ptr %p, i64 %idx) {
|
|
; CHECK-LABEL: @gep_diff_with_bitcast(
|
|
; CHECK-NEXT: ret i64 [[IDX:%.*]]
|
|
;
|
|
%i1 = getelementptr inbounds [4 x i64], ptr %p, i64 %idx
|
|
%i3 = ptrtoint ptr %i1 to i64
|
|
%i4 = ptrtoint ptr %p to i64
|
|
%i5 = sub nuw i64 %i3, %i4
|
|
%i6 = lshr i64 %i5, 5
|
|
ret i64 %i6
|
|
}
|
|
|
|
define i64 @sub_scalable(ptr noundef %val1) {
|
|
; CHECK-LABEL: @sub_scalable(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
|
|
; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 4
|
|
; CHECK-NEXT: ret i64 [[TMP1]]
|
|
;
|
|
entry:
|
|
%gep1 = getelementptr <vscale x 4 x i32>, ptr %val1, i64 1
|
|
%sub.ptr.lhs.cast.i = ptrtoint ptr %gep1 to i64
|
|
%sub.ptr.rhs.cast.i = ptrtoint ptr %val1 to i64
|
|
%sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
|
|
ret i64 %sub.ptr.sub.i
|
|
}
|
|
|
|
define i64 @sub_scalable2(ptr noundef %val1) {
|
|
; CHECK-LABEL: @sub_scalable2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
|
|
; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 4
|
|
; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()
|
|
; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl i64 [[TMP2]], 5
|
|
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i64 [[TMP1]], [[GEP2_IDX]]
|
|
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
|
;
|
|
entry:
|
|
%gep1 = getelementptr <vscale x 4 x i32>, ptr %val1, i64 1
|
|
%sub.ptr.lhs.cast.i = ptrtoint ptr %gep1 to i64
|
|
%gep2 = getelementptr <vscale x 4 x i32>, ptr %val1, i64 2
|
|
%sub.ptr.rhs.cast.i = ptrtoint ptr %gep2 to i64
|
|
%sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
|
|
ret i64 %sub.ptr.sub.i
|
|
}
|
|
|
|
define i64 @nullptrtoint_scalable_c() {
|
|
; CHECK-LABEL: @nullptrtoint_scalable_c(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
|
|
; CHECK-NEXT: [[PTR_IDX:%.*]] = shl i64 [[TMP0]], 7
|
|
; CHECK-NEXT: ret i64 [[PTR_IDX]]
|
|
;
|
|
entry:
|
|
%ptr = getelementptr inbounds <vscale x 4 x i32>, ptr null, i64 8
|
|
%ret = ptrtoint ptr %ptr to i64
|
|
ret i64 %ret
|
|
}
|
|
|
|
define i64 @nullptrtoint_scalable_x(i64 %x) {
|
|
; CHECK-LABEL: @nullptrtoint_scalable_x(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
|
|
; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 4
|
|
; CHECK-NEXT: [[PTR_IDX:%.*]] = mul nsw i64 [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i64 [[PTR_IDX]]
|
|
;
|
|
entry:
|
|
%ptr = getelementptr inbounds <vscale x 4 x i32>, ptr null, i64 %x
|
|
%ret = ptrtoint ptr %ptr to i64
|
|
ret i64 %ret
|
|
}
|
|
|
|
define i1 @_gep_phi1(ptr %str1) {
|
|
; CHECK-LABEL: @_gep_phi1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[STR1:%.*]], null
|
|
; CHECK-NEXT: br i1 [[CMP_I]], label [[_Z3FOOPKC_EXIT:%.*]], label [[LOR_LHS_FALSE_I:%.*]]
|
|
; CHECK: lor.lhs.false.i:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[STR1]], align 1
|
|
; CHECK-NEXT: [[CMP1_I:%.*]] = icmp eq i8 [[TMP0]], 0
|
|
; CHECK-NEXT: br i1 [[CMP1_I]], label [[_Z3FOOPKC_EXIT]], label [[WHILE_COND_I:%.*]]
|
|
; CHECK: while.cond.i:
|
|
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[STR1]], [[LOR_LHS_FALSE_I]] ]
|
|
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[TEST_0_I]], align 1
|
|
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP1]], 0
|
|
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
|
|
; CHECK: while.end.i:
|
|
; CHECK-NEXT: br label [[_Z3FOOPKC_EXIT]]
|
|
; CHECK: _Z3fooPKc.exit:
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = phi i1 [ true, [[WHILE_END_I]] ], [ false, [[LOR_LHS_FALSE_I]] ], [ false, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: ret i1 [[TOBOOL]]
|
|
;
|
|
entry:
|
|
%cmp.i = icmp eq ptr %str1, null
|
|
br i1 %cmp.i, label %_Z3fooPKc.exit, label %lor.lhs.false.i
|
|
|
|
lor.lhs.false.i:
|
|
%0 = load i8, ptr %str1, align 1
|
|
%cmp1.i = icmp eq i8 %0, 0
|
|
br i1 %cmp1.i, label %_Z3fooPKc.exit, label %while.cond.i
|
|
|
|
while.cond.i:
|
|
%a.pn.i = phi ptr [ %test.0.i, %while.cond.i ], [ %str1, %lor.lhs.false.i ]
|
|
%test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 1
|
|
%1 = load i8, ptr %test.0.i, align 1
|
|
%cmp3.not.i = icmp eq i8 %1, 0
|
|
br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
|
|
|
|
while.end.i:
|
|
%sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
|
|
%sub.ptr.rhs.cast.i = ptrtoint ptr %str1 to i64
|
|
%sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
|
|
br label %_Z3fooPKc.exit
|
|
|
|
_Z3fooPKc.exit:
|
|
%retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %lor.lhs.false.i ], [ 0, %entry ]
|
|
%tobool = icmp ne i64 %retval.0.i, 0
|
|
ret i1 %tobool
|
|
}
|
|
|
|
define i1 @_gep_phi2(ptr %str1, i64 %val2) {
|
|
; CHECK-LABEL: @_gep_phi2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[STR1:%.*]], null
|
|
; CHECK-NEXT: br i1 [[CMP_I]], label [[_Z3FOOPKC_EXIT:%.*]], label [[LOR_LHS_FALSE_I:%.*]]
|
|
; CHECK: lor.lhs.false.i:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[STR1]], align 1
|
|
; CHECK-NEXT: [[CMP1_I:%.*]] = icmp eq i8 [[TMP0]], 0
|
|
; CHECK-NEXT: br i1 [[CMP1_I]], label [[_Z3FOOPKC_EXIT]], label [[WHILE_COND_I:%.*]]
|
|
; CHECK: while.cond.i:
|
|
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[STR1]], [[LOR_LHS_FALSE_I]] ]
|
|
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[TEST_0_I]], align 1
|
|
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP1]], 0
|
|
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
|
|
; CHECK: while.end.i:
|
|
; CHECK-NEXT: br label [[_Z3FOOPKC_EXIT]]
|
|
; CHECK: _Z3fooPKc.exit:
|
|
; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i64 [ 1, [[WHILE_END_I]] ], [ 0, [[LOR_LHS_FALSE_I]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or i64 [[RETVAL_0_I]], [[VAL2:%.*]]
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[TMP2]], 0
|
|
; CHECK-NEXT: ret i1 [[TOBOOL]]
|
|
;
|
|
entry:
|
|
%cmp.i = icmp eq ptr %str1, null
|
|
br i1 %cmp.i, label %_Z3fooPKc.exit, label %lor.lhs.false.i
|
|
|
|
lor.lhs.false.i:
|
|
%0 = load i8, ptr %str1, align 1
|
|
%cmp1.i = icmp eq i8 %0, 0
|
|
br i1 %cmp1.i, label %_Z3fooPKc.exit, label %while.cond.i
|
|
|
|
while.cond.i:
|
|
%a.pn.i = phi ptr [ %test.0.i, %while.cond.i ], [ %str1, %lor.lhs.false.i ]
|
|
%test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 1
|
|
%1 = load i8, ptr %test.0.i, align 1
|
|
%cmp3.not.i = icmp eq i8 %1, 0
|
|
br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
|
|
|
|
while.end.i:
|
|
%sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
|
|
%sub.ptr.rhs.cast.i = ptrtoint ptr %str1 to i64
|
|
%sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
|
|
br label %_Z3fooPKc.exit
|
|
|
|
_Z3fooPKc.exit:
|
|
%retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %lor.lhs.false.i ], [ 0, %entry ]
|
|
%2 = or i64 %retval.0.i, %val2
|
|
%tobool = icmp eq i64 %2, 0
|
|
ret i1 %tobool
|
|
}
|