Simplify and optimize __fill_random_buf
authorGeorg Sauthoff <mail@gms.tf>
Thu, 30 Jun 2022 21:30:46 +0000 (23:30 +0200)
committerGeorg Sauthoff <mail@gms.tf>
Thu, 30 Jun 2022 23:12:06 +0000 (01:12 +0200)
This reduces the number of source lines and the code size.

For example, when compiling with GCC 12.1 (-O3 -march=skylake), the
resulting assembly shrinks from 33 to 27 instructions and the number of
jump instructions is reduced from 4 to 3.

NB: GCC is able to eliminate the memcpy() call.

NB: Even if a compiler doesn't eliminate the memcpy() call, it's very
unlikely to ever get called since the buffer sizes are expected to be
powers of two (>= 8), usually.

Signed-off-by: Georg Sauthoff <mail@gms.tf>
lib/rand.c

index 6e893e80ba00a4939116cb59099e881300aaed3e..e84cf65a8776036b5c78ff6871c660930f37ef1d 100644 (file)
@@ -97,29 +97,18 @@ void init_rand_seed(struct frand_state *state, uint64_t seed, bool use64)
 
 void __fill_random_buf(void *buf, unsigned int len, uint64_t seed)
 {
-       void *ptr = buf;
-
-       while (len) {
-               int this_len;
-
-               if (len >= sizeof(int64_t)) {
-                       *((int64_t *) ptr) = seed;
-                       this_len = sizeof(int64_t);
-               } else if (len >= sizeof(int32_t)) {
-                       *((int32_t *) ptr) = seed;
-                       this_len = sizeof(int32_t);
-               } else if (len >= sizeof(int16_t)) {
-                       *((int16_t *) ptr) = seed;
-                       this_len = sizeof(int16_t);
-               } else {
-                       *((int8_t *) ptr) = seed;
-                       this_len = sizeof(int8_t);
-               }
-               ptr += this_len;
-               len -= this_len;
-               seed *= GOLDEN_RATIO_PRIME;
-               seed >>= 3;
-       }
+    int64_t *b = buf;
+    int64_t *e = b  + len / sizeof *b;
+    unsigned int rest = len % sizeof *b;
+
+    for (int64_t *p = b; p != e; ++p) {
+        *p = seed;
+        seed *= GOLDEN_RATIO_PRIME;
+        seed >>= 3;
+    }
+
+    if (rest)
+        __builtin_memcpy(e, &seed, rest);
 }
 
 uint64_t fill_random_buf(struct frand_state *fs, void *buf,