llvm-project/llvm/test/Transforms/InstCombine/memchr-5.ll

285 lines
16 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; Verify that calls to memchr with arrays of elements larger than char
; are folded correctly.
; RUN: opt < %s -passes=instcombine -S -data-layout="E" | FileCheck %s --check-prefixes=BE
; RUN: opt < %s -passes=instcombine -S -data-layout="e" | FileCheck %s --check-prefixes=LE
declare i8* @memchr(i8*, i32, i64)
; BE representation: { 'a', 'b', 'c', 'd', 'e', ..., 'p' }
; LE representation: { 'd', 'c', 'b', 'a', 'h', ..., 'm' }
@a = constant [4 x i32] [i32 1633837924, i32 1701209960, i32 1768581996, i32 1835954032]
; Fold memchr(a, C, 16) for C in ['a', 'd'] U ['o', 'q'].
define void @fold_memchr_a(i64* %pcmp) {
; BE-LABEL: @fold_memchr_a(
; BE-NEXT: [[PA:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 97, i64 16)
; BE-NEXT: [[IPA:%.*]] = ptrtoint i8* [[PA]] to i64
; BE-NEXT: [[OFFA:%.*]] = sub i64 [[IPA]], ptrtoint ([4 x i32]* @a to i64)
; BE-NEXT: store i64 [[OFFA]], i64* [[PCMP:%.*]], align 4
; BE-NEXT: [[PB:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 98, i64 16)
; BE-NEXT: [[IPB:%.*]] = ptrtoint i8* [[PB]] to i64
; BE-NEXT: [[OFFB:%.*]] = sub i64 [[IPB]], ptrtoint ([4 x i32]* @a to i64)
; BE-NEXT: [[PSTOR1:%.*]] = getelementptr i64, i64* [[PCMP]], i64 1
; BE-NEXT: store i64 [[OFFB]], i64* [[PSTOR1]], align 4
; BE-NEXT: [[PC:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 99, i64 16)
; BE-NEXT: [[IPC:%.*]] = ptrtoint i8* [[PC]] to i64
; BE-NEXT: [[OFFC:%.*]] = sub i64 [[IPC]], ptrtoint ([4 x i32]* @a to i64)
; BE-NEXT: [[PSTOR2:%.*]] = getelementptr i64, i64* [[PCMP]], i64 2
; BE-NEXT: store i64 [[OFFC]], i64* [[PSTOR2]], align 4
; BE-NEXT: [[PD:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 100, i64 16)
; BE-NEXT: [[IPD:%.*]] = ptrtoint i8* [[PD]] to i64
; BE-NEXT: [[OFFD:%.*]] = sub i64 [[IPD]], ptrtoint ([4 x i32]* @a to i64)
; BE-NEXT: [[PSTOR3:%.*]] = getelementptr i64, i64* [[PCMP]], i64 3
; BE-NEXT: store i64 [[OFFD]], i64* [[PSTOR3]], align 4
; BE-NEXT: [[PN:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 110, i64 16)
; BE-NEXT: [[IPN:%.*]] = ptrtoint i8* [[PN]] to i64
; BE-NEXT: [[OFFN:%.*]] = sub i64 [[IPN]], ptrtoint ([4 x i32]* @a to i64)
; BE-NEXT: [[PSTOR4:%.*]] = getelementptr i64, i64* [[PCMP]], i64 4
; BE-NEXT: store i64 [[OFFN]], i64* [[PSTOR4]], align 4
; BE-NEXT: [[PO:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 111, i64 16)
; BE-NEXT: [[IPO:%.*]] = ptrtoint i8* [[PO]] to i64
; BE-NEXT: [[OFFO:%.*]] = sub i64 [[IPO]], ptrtoint ([4 x i32]* @a to i64)
; BE-NEXT: [[PSTOR6:%.*]] = getelementptr i64, i64* [[PCMP]], i64 6
; BE-NEXT: store i64 [[OFFO]], i64* [[PSTOR6]], align 4
; BE-NEXT: [[PP:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 112, i64 16)
; BE-NEXT: [[IPP:%.*]] = ptrtoint i8* [[PP]] to i64
; BE-NEXT: [[OFFP:%.*]] = sub i64 [[IPP]], ptrtoint ([4 x i32]* @a to i64)
; BE-NEXT: [[PSTOR7:%.*]] = getelementptr i64, i64* [[PCMP]], i64 7
; BE-NEXT: store i64 [[OFFP]], i64* [[PSTOR7]], align 4
; BE-NEXT: [[PQ:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 113, i64 16)
; BE-NEXT: [[IPQ:%.*]] = ptrtoint i8* [[PQ]] to i64
; BE-NEXT: [[PSTOR8:%.*]] = getelementptr i64, i64* [[PCMP]], i64 8
; BE-NEXT: store i64 [[IPQ]], i64* [[PSTOR8]], align 4
; BE-NEXT: ret void
;
; LE-LABEL: @fold_memchr_a(
; LE-NEXT: [[PA:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 97, i64 16)
; LE-NEXT: [[IPA:%.*]] = ptrtoint i8* [[PA]] to i64
; LE-NEXT: [[OFFA:%.*]] = sub i64 [[IPA]], ptrtoint ([4 x i32]* @a to i64)
; LE-NEXT: store i64 [[OFFA]], i64* [[PCMP:%.*]], align 4
; LE-NEXT: [[PB:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 98, i64 16)
; LE-NEXT: [[IPB:%.*]] = ptrtoint i8* [[PB]] to i64
; LE-NEXT: [[OFFB:%.*]] = sub i64 [[IPB]], ptrtoint ([4 x i32]* @a to i64)
; LE-NEXT: [[PSTOR1:%.*]] = getelementptr i64, i64* [[PCMP]], i64 1
; LE-NEXT: store i64 [[OFFB]], i64* [[PSTOR1]], align 4
; LE-NEXT: [[PC:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 99, i64 16)
; LE-NEXT: [[IPC:%.*]] = ptrtoint i8* [[PC]] to i64
; LE-NEXT: [[OFFC:%.*]] = sub i64 [[IPC]], ptrtoint ([4 x i32]* @a to i64)
; LE-NEXT: [[PSTOR2:%.*]] = getelementptr i64, i64* [[PCMP]], i64 2
; LE-NEXT: store i64 [[OFFC]], i64* [[PSTOR2]], align 4
; LE-NEXT: [[PD:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 100, i64 16)
; LE-NEXT: [[IPD:%.*]] = ptrtoint i8* [[PD]] to i64
; LE-NEXT: [[OFFD:%.*]] = sub i64 [[IPD]], ptrtoint ([4 x i32]* @a to i64)
; LE-NEXT: [[PSTOR3:%.*]] = getelementptr i64, i64* [[PCMP]], i64 3
; LE-NEXT: store i64 [[OFFD]], i64* [[PSTOR3]], align 4
; LE-NEXT: [[PN:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 110, i64 16)
; LE-NEXT: [[IPN:%.*]] = ptrtoint i8* [[PN]] to i64
; LE-NEXT: [[OFFN:%.*]] = sub i64 [[IPN]], ptrtoint ([4 x i32]* @a to i64)
; LE-NEXT: [[PSTOR4:%.*]] = getelementptr i64, i64* [[PCMP]], i64 4
; LE-NEXT: store i64 [[OFFN]], i64* [[PSTOR4]], align 4
; LE-NEXT: [[PO:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 111, i64 16)
; LE-NEXT: [[IPO:%.*]] = ptrtoint i8* [[PO]] to i64
; LE-NEXT: [[OFFO:%.*]] = sub i64 [[IPO]], ptrtoint ([4 x i32]* @a to i64)
; LE-NEXT: [[PSTOR6:%.*]] = getelementptr i64, i64* [[PCMP]], i64 6
; LE-NEXT: store i64 [[OFFO]], i64* [[PSTOR6]], align 4
; LE-NEXT: [[PP:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 112, i64 16)
; LE-NEXT: [[IPP:%.*]] = ptrtoint i8* [[PP]] to i64
; LE-NEXT: [[OFFP:%.*]] = sub i64 [[IPP]], ptrtoint ([4 x i32]* @a to i64)
; LE-NEXT: [[PSTOR7:%.*]] = getelementptr i64, i64* [[PCMP]], i64 7
; LE-NEXT: store i64 [[OFFP]], i64* [[PSTOR7]], align 4
; LE-NEXT: [[PQ:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast ([4 x i32]* @a to i8*), i32 113, i64 16)
; LE-NEXT: [[IPQ:%.*]] = ptrtoint i8* [[PQ]] to i64
; LE-NEXT: [[PSTOR8:%.*]] = getelementptr i64, i64* [[PCMP]], i64 8
; LE-NEXT: store i64 [[IPQ]], i64* [[PSTOR8]], align 4
; LE-NEXT: ret void
;
%p0 = getelementptr [4 x i32], [4 x i32]* @a, i64 0, i64 0
%p1 = bitcast i32* %p0 to i8*
%ip0 = ptrtoint [4 x i32]* @a to i64
; Fold memchr(a, 'a', 16) - a to 0 (3 in LE).
%pa = call i8* @memchr(i8* %p1, i32 97, i64 16)
%ipa = ptrtoint i8* %pa to i64
%offa = sub i64 %ipa, %ip0
%pstor0 = getelementptr i64, i64* %pcmp, i64 0
store i64 %offa, i64* %pstor0
; Fold memchr(a, 'b', 16) - a to 1 (2 in LE)
%pb = call i8* @memchr(i8* %p1, i32 98, i64 16)
%ipb = ptrtoint i8* %pb to i64
%offb = sub i64 %ipb, %ip0
%pstor1 = getelementptr i64, i64* %pcmp, i64 1
store i64 %offb, i64* %pstor1
; Fold memchr(a, 'c', 16) - a to 2 (1 in LE)
%pc = call i8* @memchr(i8* %p1, i32 99, i64 16)
%ipc = ptrtoint i8* %pc to i64
%offc = sub i64 %ipc, %ip0
%pstor2 = getelementptr i64, i64* %pcmp, i64 2
store i64 %offc, i64* %pstor2
; Fold memchr(a, 'd', 16) - a to 3 (0 in LE)
%pd = call i8* @memchr(i8* %p1, i32 100, i64 16)
%ipd = ptrtoint i8* %pd to i64
%offd = sub i64 %ipd, %ip0
%pstor3 = getelementptr i64, i64* %pcmp, i64 3
store i64 %offd, i64* %pstor3
; Fold memchr(a, 'n', 16) - a to 13 (14 in LE)
%pn = call i8* @memchr(i8* %p1, i32 110, i64 16)
%ipn = ptrtoint i8* %pn to i64
%offn = sub i64 %ipn, %ip0
%pstor4 = getelementptr i64, i64* %pcmp, i64 4
store i64 %offn, i64* %pstor4
; Fold memchr(a, 'o', 16) - a to 14 (13 in LE)
%po = call i8* @memchr(i8* %p1, i32 111, i64 16)
%ipo = ptrtoint i8* %po to i64
%offo = sub i64 %ipo, %ip0
%pstor6 = getelementptr i64, i64* %pcmp, i64 6
store i64 %offo, i64* %pstor6
; Fold memchr(a, 'p', 16) - a to 15 (12 in LE)
%pp = call i8* @memchr(i8* %p1, i32 112, i64 16)
%ipp = ptrtoint i8* %pp to i64
%offp = sub i64 %ipp, %ip0
%pstor7 = getelementptr i64, i64* %pcmp, i64 7
store i64 %offp, i64* %pstor7
; Fold memchr(a, 'q', 16) to null in both BE and LE.
%pq = call i8* @memchr(i8* %p1, i32 113, i64 16)
%ipq = ptrtoint i8* %pq to i64
%pstor8 = getelementptr i64, i64* %pcmp, i64 8
store i64 %ipq, i64* %pstor8
ret void
}
; Fold memchr(a + 1, C, 12) for C in ['e', 'h'] U ['a', 'd'].
define void @fold_memchr_a_p1(i64* %pcmp) {
; BE-LABEL: @fold_memchr_a_p1(
; BE-NEXT: [[PE:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 101, i64 12)
; BE-NEXT: [[IPE:%.*]] = ptrtoint i8* [[PE]] to i64
; BE-NEXT: [[OFFE:%.*]] = sub i64 [[IPE]], ptrtoint (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i64)
; BE-NEXT: store i64 [[OFFE]], i64* [[PCMP:%.*]], align 4
; BE-NEXT: [[PF:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 102, i64 12)
; BE-NEXT: [[IPF:%.*]] = ptrtoint i8* [[PF]] to i64
; BE-NEXT: [[OFFF:%.*]] = sub i64 [[IPF]], ptrtoint (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i64)
; BE-NEXT: [[PSTOR1:%.*]] = getelementptr i64, i64* [[PCMP]], i64 1
; BE-NEXT: store i64 [[OFFF]], i64* [[PSTOR1]], align 4
; BE-NEXT: [[PG:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 103, i64 12)
; BE-NEXT: [[IPG:%.*]] = ptrtoint i8* [[PG]] to i64
; BE-NEXT: [[OFFG:%.*]] = sub i64 [[IPG]], ptrtoint (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i64)
; BE-NEXT: [[PSTOR2:%.*]] = getelementptr i64, i64* [[PCMP]], i64 2
; BE-NEXT: store i64 [[OFFG]], i64* [[PSTOR2]], align 4
; BE-NEXT: [[PH:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 104, i64 12)
; BE-NEXT: [[IPH:%.*]] = ptrtoint i8* [[PH]] to i64
; BE-NEXT: [[OFFH:%.*]] = sub i64 [[IPH]], ptrtoint (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i64)
; BE-NEXT: [[PSTOR3:%.*]] = getelementptr i64, i64* [[PCMP]], i64 3
; BE-NEXT: store i64 [[OFFH]], i64* [[PSTOR3]], align 4
; BE-NEXT: [[PA:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 97, i64 12)
; BE-NEXT: [[IPA:%.*]] = ptrtoint i8* [[PA]] to i64
; BE-NEXT: [[PSTOR4:%.*]] = getelementptr i64, i64* [[PCMP]], i64 4
; BE-NEXT: store i64 [[IPA]], i64* [[PSTOR4]], align 4
; BE-NEXT: [[PD:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 100, i64 12)
; BE-NEXT: [[IPD:%.*]] = ptrtoint i8* [[PD]] to i64
; BE-NEXT: [[PSTOR5:%.*]] = getelementptr i64, i64* [[PCMP]], i64 5
; BE-NEXT: store i64 [[IPD]], i64* [[PSTOR5]], align 4
; BE-NEXT: ret void
;
; LE-LABEL: @fold_memchr_a_p1(
; LE-NEXT: [[PE:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 101, i64 12)
; LE-NEXT: [[IPE:%.*]] = ptrtoint i8* [[PE]] to i64
; LE-NEXT: [[OFFE:%.*]] = sub i64 [[IPE]], ptrtoint (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i64)
; LE-NEXT: store i64 [[OFFE]], i64* [[PCMP:%.*]], align 4
; LE-NEXT: [[PF:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 102, i64 12)
; LE-NEXT: [[IPF:%.*]] = ptrtoint i8* [[PF]] to i64
; LE-NEXT: [[OFFF:%.*]] = sub i64 [[IPF]], ptrtoint (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i64)
; LE-NEXT: [[PSTOR1:%.*]] = getelementptr i64, i64* [[PCMP]], i64 1
; LE-NEXT: store i64 [[OFFF]], i64* [[PSTOR1]], align 4
; LE-NEXT: [[PG:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 103, i64 12)
; LE-NEXT: [[IPG:%.*]] = ptrtoint i8* [[PG]] to i64
; LE-NEXT: [[OFFG:%.*]] = sub i64 [[IPG]], ptrtoint (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i64)
; LE-NEXT: [[PSTOR2:%.*]] = getelementptr i64, i64* [[PCMP]], i64 2
; LE-NEXT: store i64 [[OFFG]], i64* [[PSTOR2]], align 4
; LE-NEXT: [[PH:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 104, i64 12)
; LE-NEXT: [[IPH:%.*]] = ptrtoint i8* [[PH]] to i64
; LE-NEXT: [[OFFH:%.*]] = sub i64 [[IPH]], ptrtoint (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i64)
; LE-NEXT: [[PSTOR3:%.*]] = getelementptr i64, i64* [[PCMP]], i64 3
; LE-NEXT: store i64 [[OFFH]], i64* [[PSTOR3]], align 4
; LE-NEXT: [[PA:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 97, i64 12)
; LE-NEXT: [[IPA:%.*]] = ptrtoint i8* [[PA]] to i64
; LE-NEXT: [[PSTOR4:%.*]] = getelementptr i64, i64* [[PCMP]], i64 4
; LE-NEXT: store i64 [[IPA]], i64* [[PSTOR4]], align 4
; LE-NEXT: [[PD:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @a, i64 0, i64 1) to i8*), i32 100, i64 12)
; LE-NEXT: [[IPD:%.*]] = ptrtoint i8* [[PD]] to i64
; LE-NEXT: [[PSTOR5:%.*]] = getelementptr i64, i64* [[PCMP]], i64 5
; LE-NEXT: store i64 [[IPD]], i64* [[PSTOR5]], align 4
; LE-NEXT: ret void
;
%p0 = getelementptr [4 x i32], [4 x i32]* @a, i64 0, i64 1
%p1 = bitcast i32* %p0 to i8*
%ip0 = ptrtoint i8* %p1 to i64
; Fold memchr(a + 1, 'e', 12) - a to 0 (3 in LE).
%pe = call i8* @memchr(i8* %p1, i32 101, i64 12)
%ipe = ptrtoint i8* %pe to i64
%offe = sub i64 %ipe, %ip0
%pstor0 = getelementptr i64, i64* %pcmp, i64 0
store i64 %offe, i64* %pstor0
; Fold memchr(a + 1, 'f', 12) - a to 1 (2 in LE).
%pf = call i8* @memchr(i8* %p1, i32 102, i64 12)
%ipf = ptrtoint i8* %pf to i64
%offf = sub i64 %ipf, %ip0
%pstor1 = getelementptr i64, i64* %pcmp, i64 1
store i64 %offf, i64* %pstor1
; Fold memchr(a + 1, 'g', 12) - a to 2 (1 in LE).
%pg = call i8* @memchr(i8* %p1, i32 103, i64 12)
%ipg = ptrtoint i8* %pg to i64
%offg = sub i64 %ipg, %ip0
%pstor2 = getelementptr i64, i64* %pcmp, i64 2
store i64 %offg, i64* %pstor2
; Fold memchr(a + 1, 'h', 12) - a to 3 (0 in LE).
%ph = call i8* @memchr(i8* %p1, i32 104, i64 12)
%iph = ptrtoint i8* %ph to i64
%offh = sub i64 %iph, %ip0
%pstor3 = getelementptr i64, i64* %pcmp, i64 3
store i64 %offh, i64* %pstor3
; Fold memchr(a + 1, 'a', 12) to null in both BE and LE.
%pa = call i8* @memchr(i8* %p1, i32 97, i64 12)
%ipa = ptrtoint i8* %pa to i64
%pstor4 = getelementptr i64, i64* %pcmp, i64 4
store i64 %ipa, i64* %pstor4
; Fold memchr(a + 1, 'd', 12) to null in both BE and LE.
%pd = call i8* @memchr(i8* %p1, i32 100, i64 12)
%ipd = ptrtoint i8* %pd to i64
%pstor5 = getelementptr i64, i64* %pcmp, i64 5
store i64 %ipd, i64* %pstor5
ret void
}