From 3d132cee2f1ebffc9323ee6dd77b35f4cb960347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= Date: Wed, 7 Oct 2026 15:39:12 +0200 Subject: [PATCH 1/2] compiler-builtins: Introduce optimize_for_size featire passed on from core+alloc This (probably?) requires rebuilding compiler_intrinsics via build_std. --- library/alloc/Cargo.toml | 2 +- library/compiler-builtins/builtins-shim/Cargo.toml | 3 +++ library/compiler-builtins/compiler-builtins/Cargo.toml | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index a1071d2cde5f0..cc73478b80608 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -22,7 +22,7 @@ compiler_builtins = { path = "../compiler-builtins/compiler-builtins", features compiler-builtins-mem = ['compiler_builtins/mem'] compiler-builtins-c = ["compiler_builtins/c"] # Choose algorithms that are optimized for binary size instead of runtime performance -optimize_for_size = ["core/optimize_for_size"] +optimize_for_size = ["core/optimize_for_size", "compiler_builtins/optimize_for_size"] [lints.rust.unexpected_cfgs] level = "warn" diff --git a/library/compiler-builtins/builtins-shim/Cargo.toml b/library/compiler-builtins/builtins-shim/Cargo.toml index c940723a1ba5f..9ab2eac7f4fae 100644 --- a/library/compiler-builtins/builtins-shim/Cargo.toml +++ b/library/compiler-builtins/builtins-shim/Cargo.toml @@ -65,3 +65,6 @@ unmangled-names = [] # This makes certain traits and function specializations public that # are not normally public but are required by the `builtins-test` unstable-public-internals = [] + +# Choose algorithms that are optimized for binary size instead of runtime performance +optimize_for_size = [] diff --git a/library/compiler-builtins/compiler-builtins/Cargo.toml b/library/compiler-builtins/compiler-builtins/Cargo.toml index b2f1443f2eb09..226ed27eac414 100644 --- a/library/compiler-builtins/compiler-builtins/Cargo.toml +++ b/library/compiler-builtins/compiler-builtins/Cargo.toml @@ -60,3 +60,6 @@ unmangled-names = [] # This makes certain traits and function specializations public that # are not normally public but are required by the `builtins-test` unstable-public-internals = [] + +# Choose algorithms that are optimized for binary size instead of runtime performance +optimize_for_size = ["core/optimize_for_size"] From 13c657674b8065f06ecfc0b27fbd3d36ec959792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= Date: Wed, 7 Oct 2026 15:51:42 +0200 Subject: [PATCH 2/2] compiler-builtins: Add size-optimized memcpy/memmove/memset Note that this code is trivially correct, as it simply turns maybe-ifs into never-ifs. On thumbv8m.main-none-eabi with -Os, this reduces memcpy from 324 bytes to 30 bytes. The assembly is so short, I can include it in the commit message: ```arm-assembly 0000152a <__aeabi_memcpy>: 152a: 1883 adds r3, r0, r2 152c: 4298 cmp r0, r3 152e: bf28 it cs 1530: 4770 bxcs lr 1532: b580 push {r7, lr} 1534: 466f mov r7, sp 1536: ,-> f811 3b01 ldrb.w r3, [r1], #1 153a: | 3a01 subs r2, #1 153c: | f800 3b01 strb.w r3, [r0], #1 1540: '-- d1f9 bne.n 1536 <__aeabi_memcpy+0xc> 1542: e8bd 4080 ldmia.w sp!, {r7, lr} 1546: 4770 bx lr ``` memset is reduced from 100 to 26 bytes at least in simple tests. --- .../compiler-builtins/src/mem/impls.rs | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/library/compiler-builtins/compiler-builtins/src/mem/impls.rs b/library/compiler-builtins/compiler-builtins/src/mem/impls.rs index c7cfa6fb4618e..e6e2870cfa9b1 100644 --- a/library/compiler-builtins/compiler-builtins/src/mem/impls.rs +++ b/library/compiler-builtins/compiler-builtins/src/mem/impls.rs @@ -199,7 +199,7 @@ pub unsafe fn copy_forward(mut dest: *mut u8, mut src: *const u8, mut n: usize) } } - if n >= WORD_COPY_THRESHOLD { + if !cfg!(feature = "optimize_for_size") && n >= WORD_COPY_THRESHOLD { // Align dest // Because of n >= 2 * WORD_SIZE, dst_misalignment < n let dest_misalignment = (dest as usize).wrapping_neg() & WORD_MASK; @@ -318,7 +318,7 @@ pub unsafe fn copy_backward(dest: *mut u8, src: *const u8, mut n: usize) { let mut dest = dest.wrapping_add(n); let mut src = src.wrapping_add(n); - if n >= WORD_COPY_THRESHOLD { + if !cfg!(feature = "optimize_for_size") && n >= WORD_COPY_THRESHOLD { // Align dest // Because of n >= 2 * WORD_SIZE, dst_misalignment < n let dest_misalignment = dest as usize & WORD_MASK; @@ -371,20 +371,22 @@ pub unsafe fn set_bytes(mut s: *mut u8, c: u8, mut n: usize) { } } - if n >= WORD_COPY_THRESHOLD { - // Align s - // Because of n >= 2 * WORD_SIZE, dst_misalignment < n - let misalignment = (s as usize).wrapping_neg() & WORD_MASK; - set_bytes_bytes(s, c, misalignment); - s = s.wrapping_add(misalignment); - n -= misalignment; - - let n_words = n & !WORD_MASK; - set_bytes_words(s, c, n_words); - s = s.wrapping_add(n_words); - n -= n_words; - } else { - cold_path(); + if !cfg!(feature = "optimize_for_size") { + if n >= WORD_COPY_THRESHOLD { + // Align s + // Because of n >= 2 * WORD_SIZE, dst_misalignment < n + let misalignment = (s as usize).wrapping_neg() & WORD_MASK; + set_bytes_bytes(s, c, misalignment); + s = s.wrapping_add(misalignment); + n -= misalignment; + + let n_words = n & !WORD_MASK; + set_bytes_words(s, c, n_words); + s = s.wrapping_add(n_words); + n -= n_words; + } else { + cold_path(); + } } set_bytes_bytes(s, c, n); }