* The code below currently makes use of !NPY_ALIGNMENT_REQUIRED, which * should be OK but causes the clang sanitizer to warn. It may make * sense to modify the code to avoid this "unaligned" access but * it would be good to carefully check the performance changes. */
| 260 | * it would be good to carefully check the performance changes. |
| 261 | */ |
| 262 | __attribute__((no_sanitize("alignment"))) |
| 263 | #endif |
| 264 | static inline char * |
| 265 | npy_memchr(char * haystack, char needle, |
| 266 | npy_intp stride, npy_intp size, npy_intp * psubloopsize, int invert) |
| 267 | { |
| 268 | char * p = haystack; |
| 269 | npy_intp subloopsize = 0; |
| 270 | |
| 271 | if (!invert) { |
| 272 | /* |
| 273 | * this is usually the path to determine elements to process, |
| 274 | * performance less important here. |
| 275 | * memchr has large setup cost if 0 byte is close to start. |
| 276 | */ |
| 277 | while (subloopsize < size && *p != needle) { |
| 278 | subloopsize++; |
| 279 | p += stride; |
| 280 | } |
| 281 | } |
| 282 | else { |
| 283 | /* usually find elements to skip path */ |
| 284 | if (!NPY_ALIGNMENT_REQUIRED && needle == 0 && stride == 1) { |
| 285 | /* iterate until last multiple of 4 */ |
| 286 | char * block_end = haystack + size - (size % sizeof(unsigned int)); |
| 287 | while (p < block_end) { |
| 288 | unsigned int v = *(unsigned int*)p; |
| 289 | if (v != 0) { |
| 290 | break; |
| 291 | } |
| 292 | p += sizeof(unsigned int); |
| 293 | } |
| 294 | /* handle rest */ |
| 295 | subloopsize = (p - haystack); |
| 296 | } |
| 297 | while (subloopsize < size && *p == needle) { |
| 298 | subloopsize++; |
| 299 | p += stride; |
| 300 | } |
| 301 | } |
| 302 | |
| 303 | *psubloopsize = subloopsize; |
| 304 | |
| 305 | return p; |
| 306 | } |
| 307 | |
| 308 | |
| 309 | /* |
no outgoing calls
no test coverage detected