[LLD][COFF] Emit tail merge pdata for delay load thunks on ARM64EC (#116810)
[llvm-project.git] / libc / AOR_v20.02 / string / aarch64 / strrchr-sve.S
blobc04be74068ed73ddcd28bfc50eeeb80d557c8c74
1 /*
2  * strrchr - find the last of a character in a string
3  *
4  * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5  * See https://llvm.org/LICENSE.txt for license information.
6  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7  */
9 #if __ARM_FEATURE_SVE
10 /* Assumptions:
11  *
12  * ARMv8-a, AArch64
13  * SVE Available.
14  */
16         .arch   armv8-a+sve
17         .text
19         .globl  __strrchr_aarch64_sve
20         .type   __strrchr_aarch64_sve, %function
21         .p2align 4
22 __strrchr_aarch64_sve:
23         dup     z1.b, w1                /* replicate byte across vector */
24         setffr                          /* initialize FFR */
25         ptrue   p1.b                    /* all ones; loop invariant */
26         mov     x2, 0                   /* no match found so far */
27         pfalse  p2.b
29         .p2align 4
30         /* Read a vector's worth of bytes, stopping on first fault.  */
31 0:      ldff1b  z0.b, p1/z, [x0, xzr]
32         rdffrs  p0.b, p1/z
33         b.nlast 1f
35         /* First fault did not fail: the whole vector is valid.
36            Avoid depending on the contents of FFR beyond the branch.  */
37         incb    x0, all                 /* skip bytes this round */
38         cmpeq   p3.b, p1/z, z0.b, 0     /* search for 0 */
39         b.any   3f
41         cmpeq   p3.b, p1/z, z0.b, z1.b  /* search for c; no eos */
42         b.none  0b
44         mov     x2, x0                  /* save advanced base */
45         mov     p2.b, p3.b              /* save current search */
46         b       0b
48         /* First fault failed: only some of the vector is valid.
49            Perform the comparisons only on the valid bytes.  */
50 1:      cmpeq   p3.b, p0/z, z0.b, 0     /* search for 0 */
51         b.any   2f
53         cmpeq   p3.b, p0/z, z0.b, z1.b  /* search for c; no eos */
54         mov     x3, x0
55         incp    x0, p0.b                /* skip bytes this round */
56         setffr                          /* re-init FFR */
57         b.none  0b
59         addvl   x2, x3, 1               /* save advanced base */
60         mov     p2.b, p3.b              /* save current search */
61         b       0b
63         /* Found end-of-string.  */
64 2:      incb    x0, all                 /* advance base */
65 3:      brka    p3.b, p1/z, p3.b        /* mask after first 0 */
66         cmpeq   p3.b, p3/z, z0.b, z1.b  /* search for c not after eos */
67         b.any   4f
69         /* No C within last vector.  Did we have one before?  */
70         cbz     x2, 5f
71         mov     x0, x2                  /* restore advanced base */
72         mov     p3.b, p2.b              /* restore saved search */
74         /* Find the *last* match in the predicate.  This is slightly
75            more complicated than finding the first match.  */
76 4:      rev     p3.b, p3.b              /* reverse the bits */
77         brka    p3.b, p1/z, p3.b        /* find position of last match */
78         decp    x0, p3.b                /* retard pointer to last match */
79         ret
81         /* No C whatsoever.  Return NULL.  */
82 5:      mov     x0, 0
83         ret
85         .size   __strrchr_aarch64_sve, . - __strrchr_aarch64_sve
86 #endif