diff --git a/include/cityhash.h b/include/cityhash.h
index 3b2d1e84b5b3..346fb673a07d 100644
--- a/include/cityhash.h
+++ b/include/cityhash.h
@@ -32,6 +32,13 @@
extern "C" {
#endif
+/*
+ * Define 1/2/3-argument specialized versions of cityhash4, which can reduce
+ * instruction count (especially multiplication) on some 32-bit arches.
+ */
+_SYS_CITYHASH_H uint64_t cityhash1(uint64_t);
+_SYS_CITYHASH_H uint64_t cityhash2(uint64_t, uint64_t);
+_SYS_CITYHASH_H uint64_t cityhash3(uint64_t, uint64_t, uint64_t);
_SYS_CITYHASH_H uint64_t cityhash4(uint64_t, uint64_t, uint64_t, uint64_t);
#ifdef __cplusplus
diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi
index 51b29643ee0c..fab97ada68dc 100644
--- a/lib/libzfs/libzfs.abi
+++ b/lib/libzfs/libzfs.abi
@@ -153,6 +153,9 @@
+
+
+
@@ -9179,6 +9182,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/module/zcommon/cityhash.c b/module/zcommon/cityhash.c
index 413a96df2cda..c758ec47d1f6 100644
--- a/module/zcommon/cityhash.c
+++ b/module/zcommon/cityhash.c
@@ -49,8 +49,8 @@ cityhash_helper(uint64_t u, uint64_t v, uint64_t mul)
return (b);
}
-uint64_t
-cityhash4(uint64_t w1, uint64_t w2, uint64_t w3, uint64_t w4)
+static inline uint64_t
+cityhash_impl(uint64_t w1, uint64_t w2, uint64_t w3, uint64_t w4)
{
uint64_t mul = HASH_K2 + 64;
uint64_t a = w1 * HASH_K1;
@@ -59,9 +59,38 @@ cityhash4(uint64_t w1, uint64_t w2, uint64_t w3, uint64_t w4)
uint64_t d = w3 * HASH_K2;
return (cityhash_helper(rotate(a + b, 43) + rotate(c, 30) + d,
a + rotate(b + HASH_K2, 18) + c, mul));
+}
+/*
+ * Passing w as the 2nd argument could save one 64-bit multiplication.
+ */
+uint64_t
+cityhash1(uint64_t w)
+{
+ return (cityhash_impl(0, w, 0, 0));
+}
+
+uint64_t
+cityhash2(uint64_t w1, uint64_t w2)
+{
+ return (cityhash_impl(w1, w2, 0, 0));
+}
+
+uint64_t
+cityhash3(uint64_t w1, uint64_t w2, uint64_t w3)
+{
+ return (cityhash_impl(w1, w2, w3, 0));
+}
+
+uint64_t
+cityhash4(uint64_t w1, uint64_t w2, uint64_t w3, uint64_t w4)
+{
+ return (cityhash_impl(w1, w2, w3, w4));
}
#if defined(_KERNEL)
+EXPORT_SYMBOL(cityhash1);
+EXPORT_SYMBOL(cityhash2);
+EXPORT_SYMBOL(cityhash3);
EXPORT_SYMBOL(cityhash4);
#endif