summaryrefslogtreecommitdiff
path: root/src/system.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/system.h')
-rw-r--r--src/system.h72
1 files changed, 54 insertions, 18 deletions
diff --git a/src/system.h b/src/system.h
index 8f6a2ea84..1cd6bdb44 100644
--- a/src/system.h
+++ b/src/system.h
@@ -427,6 +427,15 @@ enum
# define ATTRIBUTE_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
#endif
+#ifdef __GNUC__
+# define LIKELY(cond) __builtin_expect ((cond), 1)
+# define UNLIKELY(cond) __builtin_expect ((cond), 0)
+#else
+# define LIKELY(cond) (cond)
+# define UNLIKELY(cond) (cond)
+#endif
+
+
#if defined strdupa
# define ASSIGN_STRDUPA(DEST, S) \
do { DEST = strdupa (S); } while (0)
@@ -487,27 +496,54 @@ ptr_align (void const *ptr, size_t alignment)
}
/* Return whether the buffer consists entirely of NULs.
- Note the word after the buffer must be non NUL. */
+ Based on memeqzero in CCAN by Rusty Russell under CC0 (Public domain). */
static inline bool _GL_ATTRIBUTE_PURE
-is_nul (void const *buf, size_t bufsize)
+is_nul (void const *buf, size_t length)
{
- typedef uintptr_t word;
- void const *vp;
- char const *cbuf = buf;
- word const *wp = buf;
-
- /* Find first nonzero *word*, or the word with the sentinel. */
- while (*wp++ == 0)
- continue;
-
- /* Find the first nonzero *byte*, or the sentinel. */
- vp = wp - 1;
- char const *cp = vp;
- while (*cp++ == 0)
- continue;
-
- return cbuf + bufsize < cp;
+ const unsigned char *p = buf;
+/* Using possibly unaligned access for the first 16 bytes
+ saves about 30-40 cycles, though it is strictly undefined behavior
+ and so would need __attribute__ ((__no_sanitize_undefined__))
+ to avoid -fsanitize=undefined warnings.
+ Considering coreutils is mainly concerned with relatively
+ large buffers, we'll just use the defined behavior. */
+#if 0 && _STRING_ARCH_unaligned
+ unsigned long word;
+#else
+ unsigned char word;
+#endif
+
+ if (! length)
+ return true;
+
+ /* Check len bytes not aligned on a word. */
+ while (UNLIKELY (length & (sizeof word - 1)))
+ {
+ if (*p)
+ return false;
+ p++;
+ length--;
+ if (! length)
+ return true;
+ }
+
+ /* Check up to 16 bytes a word at a time. */
+ for (;;)
+ {
+ memcpy (&word, p, sizeof word);
+ if (word)
+ return false;
+ p += sizeof word;
+ length -= sizeof word;
+ if (! length)
+ return true;
+ if (UNLIKELY (length & 15) == 0)
+ break;
+ }
+
+ /* Now we know first 16 bytes are NUL, memcmp with self. */
+ return memcmp (buf, p, length) == 0;
}
/* If 10*Accum + Digit_val is larger than the maximum value for Type,