Compiler projects using llvm
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; Verify that calls to memrchr 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* @memrchr(i8*, i32, i64)

; BE representation: { 'a', 'b', 'c', 'd', 'e', ..., 'p', 'a', 'b', 'c', 'd' }
; LE representation: { 'd', 'c', 'b', 'a', 'h', ..., 'm', 'd', 'c', 'b', 'a' }
@a = constant [5 x i32] [i32 1633837924, i32 1701209960, i32 1768581996, i32 1835954032, i32 1633837924]


; Fold memrchr(a, C, 16) for C in ['a', 'd'] U ['o', 'q'].

define void @fold_memrchr_a_16(i64* %pcmp) {
; BE-LABEL: @fold_memrchr_a_16(
; BE-NEXT:    store i64 0, i64* [[PCMP:%.*]], align 4
; BE-NEXT:    [[PSTOR1:%.*]] = getelementptr i64, i64* [[PCMP]], i64 1
; BE-NEXT:    store i64 1, i64* [[PSTOR1]], align 4
; BE-NEXT:    [[PSTOR2:%.*]] = getelementptr i64, i64* [[PCMP]], i64 2
; BE-NEXT:    store i64 2, i64* [[PSTOR2]], align 4
; BE-NEXT:    [[PSTOR3:%.*]] = getelementptr i64, i64* [[PCMP]], i64 3
; BE-NEXT:    store i64 3, i64* [[PSTOR3]], align 4
; BE-NEXT:    [[PSTOR4:%.*]] = getelementptr i64, i64* [[PCMP]], i64 4
; BE-NEXT:    store i64 13, i64* [[PSTOR4]], align 4
; BE-NEXT:    [[PSTOR6:%.*]] = getelementptr i64, i64* [[PCMP]], i64 6
; BE-NEXT:    store i64 14, i64* [[PSTOR6]], align 4
; BE-NEXT:    [[PSTOR7:%.*]] = getelementptr i64, i64* [[PCMP]], i64 7
; BE-NEXT:    store i64 15, i64* [[PSTOR7]], align 4
; BE-NEXT:    [[PSTOR8:%.*]] = getelementptr i64, i64* [[PCMP]], i64 8
; BE-NEXT:    store i64 0, i64* [[PSTOR8]], align 4
; BE-NEXT:    ret void
;
; LE-LABEL: @fold_memrchr_a_16(
; LE-NEXT:    store i64 3, i64* [[PCMP:%.*]], align 4
; LE-NEXT:    [[PSTOR1:%.*]] = getelementptr i64, i64* [[PCMP]], i64 1
; LE-NEXT:    store i64 2, i64* [[PSTOR1]], align 4
; LE-NEXT:    [[PSTOR2:%.*]] = getelementptr i64, i64* [[PCMP]], i64 2
; LE-NEXT:    store i64 1, i64* [[PSTOR2]], align 4
; LE-NEXT:    [[PSTOR3:%.*]] = getelementptr i64, i64* [[PCMP]], i64 3
; LE-NEXT:    store i64 0, i64* [[PSTOR3]], align 4
; LE-NEXT:    [[PSTOR4:%.*]] = getelementptr i64, i64* [[PCMP]], i64 4
; LE-NEXT:    store i64 14, i64* [[PSTOR4]], align 4
; LE-NEXT:    [[PSTOR6:%.*]] = getelementptr i64, i64* [[PCMP]], i64 6
; LE-NEXT:    store i64 13, i64* [[PSTOR6]], align 4
; LE-NEXT:    [[PSTOR7:%.*]] = getelementptr i64, i64* [[PCMP]], i64 7
; LE-NEXT:    store i64 12, i64* [[PSTOR7]], align 4
; LE-NEXT:    [[PSTOR8:%.*]] = getelementptr i64, i64* [[PCMP]], i64 8
; LE-NEXT:    store i64 0, i64* [[PSTOR8]], align 4
; LE-NEXT:    ret void
;
  %p0 = getelementptr [5 x i32], [5 x i32]* @a, i64 0, i64 0
  %p1 = bitcast i32* %p0 to i8*
  %ip0 = ptrtoint [5 x i32]* @a to i64

; Fold memrchr(a, 'a', 16) - a to 0 (3 in LE).

  %pa = call i8* @memrchr(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 memrchr(a, 'b', 16) - a to 1 (2 in LE)

  %pb = call i8* @memrchr(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 memrchr(a, 'c', 16) - a to 2 (1 in LE)

  %pc = call i8* @memrchr(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 memrchr(a, 'd', 16) - a to 3 (0 in LE)

  %pd = call i8* @memrchr(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 memrchr(a, 'n', 16) - a to 13 (14 in LE)

  %pn = call i8* @memrchr(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 memrchr(a, 'o', 16) - a to 14 (13 in LE)

  %po = call i8* @memrchr(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 memrchr(a, 'p', 16) - a to 15 (12 in LE)

  %pp = call i8* @memrchr(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 memrchr(a, 'q', 16) to null in both BE and LE.

  %pq = call i8* @memrchr(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 memrchr(a + 1, C, 12) for C in ['e', 'h'] U ['a', 'd'].

define void @fold_memrchr_a_p1_16(i64* %pcmp) {
; BE-LABEL: @fold_memrchr_a_p1_16(
; BE-NEXT:    store i64 0, i64* [[PCMP:%.*]], align 4
; BE-NEXT:    [[PSTOR1:%.*]] = getelementptr i64, i64* [[PCMP]], i64 1
; BE-NEXT:    store i64 1, i64* [[PSTOR1]], align 4
; BE-NEXT:    [[PSTOR2:%.*]] = getelementptr i64, i64* [[PCMP]], i64 2
; BE-NEXT:    store i64 2, i64* [[PSTOR2]], align 4
; BE-NEXT:    [[PSTOR3:%.*]] = getelementptr i64, i64* [[PCMP]], i64 3
; BE-NEXT:    store i64 3, i64* [[PSTOR3]], align 4
; BE-NEXT:    [[PSTOR4:%.*]] = getelementptr i64, i64* [[PCMP]], i64 4
; BE-NEXT:    store i64 0, i64* [[PSTOR4]], align 4
; BE-NEXT:    [[PSTOR5:%.*]] = getelementptr i64, i64* [[PCMP]], i64 5
; BE-NEXT:    store i64 0, i64* [[PSTOR5]], align 4
; BE-NEXT:    ret void
;
; LE-LABEL: @fold_memrchr_a_p1_16(
; LE-NEXT:    store i64 3, i64* [[PCMP:%.*]], align 4
; LE-NEXT:    [[PSTOR1:%.*]] = getelementptr i64, i64* [[PCMP]], i64 1
; LE-NEXT:    store i64 2, i64* [[PSTOR1]], align 4
; LE-NEXT:    [[PSTOR2:%.*]] = getelementptr i64, i64* [[PCMP]], i64 2
; LE-NEXT:    store i64 1, i64* [[PSTOR2]], align 4
; LE-NEXT:    [[PSTOR3:%.*]] = getelementptr i64, i64* [[PCMP]], i64 3
; LE-NEXT:    store i64 0, i64* [[PSTOR3]], align 4
; LE-NEXT:    [[PSTOR4:%.*]] = getelementptr i64, i64* [[PCMP]], i64 4
; LE-NEXT:    store i64 0, i64* [[PSTOR4]], align 4
; LE-NEXT:    [[PSTOR5:%.*]] = getelementptr i64, i64* [[PCMP]], i64 5
; LE-NEXT:    store i64 0, i64* [[PSTOR5]], align 4
; LE-NEXT:    ret void
;
  %p0 = getelementptr [5 x i32], [5 x i32]* @a, i64 0, i64 1
  %p1 = bitcast i32* %p0 to i8*
  %ip0 = ptrtoint i8* %p1 to i64

; Fold memrchr(a + 1, 'e', 12) - a to 0 (3 in LE).

  %pe = call i8* @memrchr(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 memrchr(a + 1, 'f', 12) - a to 1 (2 in LE).

  %pf = call i8* @memrchr(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 memrchr(a + 1, 'g', 12) - a to 2 (1 in LE).

  %pg = call i8* @memrchr(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 memrchr(a + 1, 'h', 12) - a to 3 (0 in LE).

  %ph = call i8* @memrchr(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 memrchr(a + 1, 'a', 12) to null in both BE and LE.

  %pa = call i8* @memrchr(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 memrchr(a + 1, 'd', 12) to null in both BE and LE.

  %pd = call i8* @memrchr(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
}


; Fold memrchr(a, C, 20) for C in ['a', 'e'].

define void @fold_memrchr_a_20(i64* %pcmp) {
; BE-LABEL: @fold_memrchr_a_20(
; BE-NEXT:    store i64 16, i64* [[PCMP:%.*]], align 4
; BE-NEXT:    [[PSTOR1:%.*]] = getelementptr i64, i64* [[PCMP]], i64 1
; BE-NEXT:    store i64 17, i64* [[PSTOR1]], align 4
; BE-NEXT:    [[PSTOR2:%.*]] = getelementptr i64, i64* [[PCMP]], i64 2
; BE-NEXT:    store i64 18, i64* [[PSTOR2]], align 4
; BE-NEXT:    [[PSTOR3:%.*]] = getelementptr i64, i64* [[PCMP]], i64 3
; BE-NEXT:    store i64 19, i64* [[PSTOR3]], align 4
; BE-NEXT:    [[PSTOR4:%.*]] = getelementptr i64, i64* [[PCMP]], i64 4
; BE-NEXT:    store i64 4, i64* [[PSTOR4]], align 4
; BE-NEXT:    ret void
;
; LE-LABEL: @fold_memrchr_a_20(
; LE-NEXT:    store i64 19, i64* [[PCMP:%.*]], align 4
; LE-NEXT:    [[PSTOR1:%.*]] = getelementptr i64, i64* [[PCMP]], i64 1
; LE-NEXT:    store i64 18, i64* [[PSTOR1]], align 4
; LE-NEXT:    [[PSTOR2:%.*]] = getelementptr i64, i64* [[PCMP]], i64 2
; LE-NEXT:    store i64 17, i64* [[PSTOR2]], align 4
; LE-NEXT:    [[PSTOR3:%.*]] = getelementptr i64, i64* [[PCMP]], i64 3
; LE-NEXT:    store i64 16, i64* [[PSTOR3]], align 4
; LE-NEXT:    [[PSTOR4:%.*]] = getelementptr i64, i64* [[PCMP]], i64 4
; LE-NEXT:    store i64 7, i64* [[PSTOR4]], align 4
; LE-NEXT:    ret void
;
  %p0 = getelementptr [5 x i32], [5 x i32]* @a, i64 0, i64 0
  %p1 = bitcast i32* %p0 to i8*
  %ip0 = ptrtoint i8* %p1 to i64

; Fold memrchr(a, 'a', 20) - a to 16 (19 in LE).

  %pa = call i8* @memrchr(i8* %p1, i32 97, i64 20)
  %ipa = ptrtoint i8* %pa to i64
  %offa = sub i64 %ipa, %ip0
  %pstor0 = getelementptr i64, i64* %pcmp, i64 0
  store i64 %offa, i64* %pstor0

; Fold memrchr(a, 'b', 16) - a to 17 (18 in LE)

  %pb = call i8* @memrchr(i8* %p1, i32 98, i64 20)
  %ipb = ptrtoint i8* %pb to i64
  %offb = sub i64 %ipb, %ip0
  %pstor1 = getelementptr i64, i64* %pcmp, i64 1
  store i64 %offb, i64* %pstor1

; Fold memrchr(a, 'c', 16) - a to 18 (17 in LE)

  %pc = call i8* @memrchr(i8* %p1, i32 99, i64 20)
  %ipc = ptrtoint i8* %pc to i64
  %offc = sub i64 %ipc, %ip0
  %pstor2 = getelementptr i64, i64* %pcmp, i64 2
  store i64 %offc, i64* %pstor2

; Fold memrchr(a, 'd', 16) - a to 19 (16 in LE)

  %pd = call i8* @memrchr(i8* %p1, i32 100, i64 20)
  %ipd = ptrtoint i8* %pd to i64
  %offd = sub i64 %ipd, %ip0
  %pstor3 = getelementptr i64, i64* %pcmp, i64 3
  store i64 %offd, i64* %pstor3

; Fold memrchr(a, 'e', 16) - a to 4 (7 in LE)

  %pe = call i8* @memrchr(i8* %p1, i32 101, i64 20)
  %ipe = ptrtoint i8* %pe to i64
  %offe = sub i64 %ipe, %ip0
  %pstor4 = getelementptr i64, i64* %pcmp, i64 4
  store i64 %offe, i64* %pstor4

  ret void
}