From eb29fad4b2649eaf36b599d02ace10e734ef9c58 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Fri, 14 Feb 2025 13:51:59 +0100
Subject: [PATCH] code size benchmark: separate morph function to avoid
 overhead from scanf/printf

---
 morphisms/Makefile                      |  8 +--
 morphisms/posint-dec-to-hex-generated.c | 53 ++++++-------------
 morphisms/posint-dec-to-hex-optimal.c   | 69 +++++++++++++------------
 3 files changed, 56 insertions(+), 74 deletions(-)

diff --git a/morphisms/Makefile b/morphisms/Makefile
index 439499a..884f9dc 100644
--- a/morphisms/Makefile
+++ b/morphisms/Makefile
@@ -22,10 +22,10 @@ code-size-benchmark: posint-dec-to-hex-generated-gcc \
 					posint-dec-to-hex-generated-clang \
 				 	posint-dec-to-hex-optimal-gcc \
 					posint-dec-to-hex-optimal-clang
-	INST_COUNT_GEN_GCC=$(shell gdb --batch -ex "file posint-dec-to-hex-generated-gcc" -ex "disassemble main" | wc -l)
-	INST_COUNT_GEN_CLANG=$(shell gdb --batch -ex "file posint-dec-to-hex-generated-clang" -ex "disassemble main" | wc -l)
-	INST_COUNT_OPT_GCC=$(shell gdb --batch -ex "file posint-dec-to-hex-optimal-gcc" -ex "disassemble main" | wc -l)
-	INST_COUNT_OPT_CLANG=$(shell gdb --batch -ex "file posint-dec-to-hex-optimal-clang" -ex "disassemble main" | wc -l)
+	INST_COUNT_GEN_GCC=$(shell gdb --batch -ex "file posint-dec-to-hex-generated-gcc" -ex "disassemble morph_posint_radix" | wc -l)
+	INST_COUNT_GEN_CLANG=$(shell gdb --batch -ex "file posint-dec-to-hex-generated-clang" -ex "disassemble morph_posint_radix" | wc -l)
+	INST_COUNT_OPT_GCC=$(shell gdb --batch -ex "file posint-dec-to-hex-optimal-gcc" -ex "disassemble morph_posint_radix" | wc -l)
+	INST_COUNT_OPT_CLANG=$(shell gdb --batch -ex "file posint-dec-to-hex-optimal-clang" -ex "disassemble posint_radix" | wc -l)
 
 clean:
 	rm $(TARGETS)
diff --git a/morphisms/posint-dec-to-hex-generated.c b/morphisms/posint-dec-to-hex-generated.c
index a942e66..bdba861 100644
--- a/morphisms/posint-dec-to-hex-generated.c
+++ b/morphisms/posint-dec-to-hex-generated.c
@@ -3,12 +3,11 @@
 #include <morphisms/length-prefix.h>
 #include <morphisms/posint.h>
 
-int main() {
-    uint8_t bufA[1024];
-    uint8_t bufB[1024];
-
-    scanf("%s", bufA);
-
+__attribute__((noinline))
+int morph_posint_radix(
+    uint8_t * bufA,
+    uint8_t * bufB
+) {
     // morph to
     //     ℕ ~ <PosInt 10 BigEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ Char ~ Ascii]
     {
@@ -23,40 +22,14 @@ int main() {
         struct LengthPrefixUInt8Array * src = (void*) bufB;
         struct LengthPrefixUInt64Array * dst = (void*) bufA;
         length_prefix_array_map_8_to_64( morph_digit_as_char_to_uint64, src, dst );
-/*
-        dst->len = src->len;
-        for( uint64_t i = 0; i < src->len; ++i )
-            morph_digit_as_char_to_uint64( &src->items[i], &dst->items[i] );
-*/
     }
-
-    // morph to
-    //    ℕ ~ <PosInt 10 LittleEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ ℤ_10 ~ x86.UInt64]
-    {
-        uint64_t const radix = 10;
-        struct LengthPrefixUInt64Array * src = (void*) bufA;
-        struct LengthPrefixUInt64Array * dst = (void*) bufB;
-        morph_posint_endianness( radix, src, dst );
-    }
-
-    // morph to
     //    ℕ ~ <PosInt 16 LittleEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 16> ~ ℤ_16 ~ x86.UInt64]
     {
         uint64_t const src_radix = 10;
         uint64_t const dst_radix = 16;
         struct LengthPrefixUInt64Array * src = (void*) bufB;
         struct LengthPrefixUInt64Array * dst = (void*) bufA;
-        morph_posint_radix( src_radix, dst_radix, src, dst );
-    }
-
-
-    // morph to
-    //    ℕ ~ <PosInt 16 LittleEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ ℤ_10 ~ x86.UInt64]
-    {
-        uint64_t const radix = 16;
-        struct LengthPrefixUInt64Array * src = (void*) bufA;
-        struct LengthPrefixUInt64Array * dst = (void*) bufB;
-        morph_posint_endianness( radix, src, dst );
+        morph_posint_radix_little( src_radix, dst_radix, src, dst );
     }
 
     // morph to
@@ -66,11 +39,6 @@ int main() {
         struct LengthPrefixUInt8Array * dst = (void*) bufA;
 
         length_prefix_array_map_64_to_8( morph_digit_as_uint64_to_char, src, dst );
-/*
-        dst->len = src->len;
-        for( uint64_t i = 0; i < src->len; ++i )
-            morph_digit_as_uint64_to_char( &src->items[i], &dst->items[i] );
-*/
     }
 
     // morph to
@@ -81,6 +49,15 @@ int main() {
         morph_string_as_length_prefix_to_nullterm( src, dst );
     }
 
+    return 0;
+}
+
+int main() {
+    uint8_t bufA[1024];
+    uint8_t bufB[1024];
+
+    scanf("%s", bufA);
+    morph_posint_radix( bufA, bufB );
     printf("%s\n", bufB);
 
     return 0;
diff --git a/morphisms/posint-dec-to-hex-optimal.c b/morphisms/posint-dec-to-hex-optimal.c
index 7118ae0..b9c1ab0 100644
--- a/morphisms/posint-dec-to-hex-optimal.c
+++ b/morphisms/posint-dec-to-hex-optimal.c
@@ -1,6 +1,42 @@
 #include <stdio.h>
 #include <stdint.h>
 
+__attribute__((noinline))
+int morph_posint_radix( char * in, char * out ) {
+    uint64_t value = 0;
+        while( *in ) {
+            if( *in >= '0' && *in <= '9' ) {
+                value *= 10;
+                value += *in - '0';
+            }
+            else
+                return -1;
+
+            in++;
+        }
+
+        uint64_t v = value;
+        while( v ) {
+            out ++;
+            v /= 16;
+        }
+
+        *out-- = '\0';
+        while( value ) {
+            unsigned digit = value % 16;
+            if( digit < 10 ) {
+                *out-- = digit + '0';
+            } else if( digit < 16 ) {
+                *out-- = digit + 'a' - 10;
+            } else {
+                return -1;
+            }
+            value /= 16;
+        }
+
+    return 0;
+}
+
 int main() {
     char bufA[1024];
     char bufB[1024];
@@ -9,38 +45,7 @@ int main() {
     char * out = bufB;
 
     scanf("%s", in);
-
-    uint64_t value = 0;
-    while( *in ) {
-        if( *in >= '0' && *in <= '9' ) {
-            value *= 10;
-            value += *in - '0';
-        }
-        else
-            return -1;
-
-        in++;
-    }
-
-    uint64_t v = value;
-    while( v ) {
-        out ++;
-        v /= 16;
-    }
-
-    *out-- = '\0';
-    while( value ) {
-        unsigned digit = value % 16;
-        if( digit < 10 ) {
-            *out-- = digit + '0';
-        } else if( digit < 16 ) {
-            *out-- = digit + 'a' - 10;
-        } else {
-            return -1;
-        }
-        value /= 16;
-    }
-
+    morph_posint_radix( in, out );
     printf("%s\n", out);
 
     return 0;