From 89b84846d10ab803ef1bcf6f9a4cbcdea45f7c96 Mon Sep 17 00:00:00 2001
From: Petr Rockai <me@mornfall.net>
Date: Mon, 22 Jul 2019 20:10:36 +0000
Subject: [PATCH] libc: Optimize memcpy a little.

---
 dios/libc/string/memcpy.c | 36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/dios/libc/string/memcpy.c b/dios/libc/string/memcpy.c
index 55192cdd3..5b95840ee 100644
--- a/dios/libc/string/memcpy.c
+++ b/dios/libc/string/memcpy.c
@@ -6,15 +6,45 @@
 
 #include <string.h>
 #include <assert.h>
+#include <stdint.h>
 
 #ifndef REGTEST
 
-__attribute__((__annotate__("divine.link.always")))
-__attribute__((optnone)) /* do not replace the memmove call below with a (recursive) memcpy */
+__link_always __skipcfl
 void * memcpy( void * _PDCLIB_restrict s1, const void * _PDCLIB_restrict s2, size_t n )
 {
     assert( s1 < s2 ? s1 + n <= s2 : s2 + n <= s1 );
-    return memmove( s1, (void *)s2, n );
+
+    char *dst = ( char * ) s1;
+    const char *src = ( const char * ) s2;
+
+    switch ( n )
+    {
+        case 1: *dst = *src; return s1;
+        case 2: *( uint16_t * ) dst = *( uint16_t * ) src; return s1;
+        case 4: *( uint32_t * ) dst = *( uint32_t * ) src; return s1;
+        case 8: *( uint64_t * ) dst = *( uint64_t * ) src; return s1;
+        default:
+        {
+            while ( ( uint64_t ) dst % 8 && ( uint64_t ) src % 8 && n )
+                *dst++ = *src++, n --;
+
+            uint64_t *src_l = ( uint64_t * ) src;
+            uint64_t *dst_l = ( uint64_t * ) dst;
+
+            while ( n >= 8 )
+            {
+                *dst_l++ = *src_l++;
+                n -= 8;
+            }
+
+            src = ( const char * ) src_l;
+            dst = ( char *) dst_l;
+            while ( n-- )
+                *dst++ = *src++;
+        }
+        return s1;
+    }
 }
 
 #endif
-- 
GitLab