Skip to content

Optimize memset/memcpy size - #1333

Merged
clarfonthey merged 4 commits into
rust-lang:mainfrom
kleinesfilmroellchen:optimize-memset-size
Nov 6, 2026
Merged

clarfonthey merged 4 commits into
rust-lang:mainfrom
kleinesfilmroellchen:optimize-memset-size

Conversation

@kleinesfilmroellchen

Copy link
Copy Markdown
Contributor

Tracking issue: rust-lang/rust#125612

On thumbv8m.main-none-eabi with -Os, this reduces memcpy from 324 bytes to 30 bytes. The assembly is so short and cute UwU, I can include it here:

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.

Actually using this requires optimize_for_size in alloc, like the original version of this PR. I’ll make a separate r-l/r PR once this is merged to do that.

I’ve done some testing on multiple ARM embedded targets, but overall this code should be trivially correct. The previous if <size-dependent condition> are simply turned into if false with the flag, always using the bytewise copy/write branch.

@diondokter

r? @clarfonthey

… core+alloc

This (probably?) requires rebuilding compiler_intrinsics via build_std.
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], rust-lang#1
    153a:       |   3a01        subs    r2, rust-lang#1
    153c:       |   f800 3b01   strb.w  r3, [r0], rust-lang#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.
@rustbot

rustbot commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Warning ⚠️

  • There are uncanonicalized issue links (such as #123) in the commit messages of the following commits.
    Please add the organization and repository before the issue number (like so rust-lang/compiler-builtins#123) to avoid issues with subtrees.

@rustbot

rustbot commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

Error: Failed to set assignee to clarfonthey: invalid assignee

Note: Only org members with at least the repository "read" role, users with write permissions, or people who have commented on the PR may be assigned.

Please file an issue on GitHub at triagebot if there's a problem with this bot, or reach out on #triagebot on Zulip.

@kleinesfilmroellchen

Copy link
Copy Markdown
Contributor Author

r? libs

@clarfonthey

Copy link
Copy Markdown
Contributor

(note: compiler-builtins is managed by crate-maintainers, not libs. not sure if @tgross35 is the only intersection of those two, but regardless, you should just let rustbot auto-assign here)

@kleinesfilmroellchen

Copy link
Copy Markdown
Contributor Author

r?

@rustbot

rustbot commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

Error: Parsing assign command in comment failed: specify user to assign to (if you want to reroll without a specific reviewer in mind, use @rustbot reroll)

Please file an issue on GitHub at triagebot if there's a problem with this bot, or reach out on #triagebot on Zulip.

@kleinesfilmroellchen

Copy link
Copy Markdown
Contributor Author

@rustbot reroll

(excuse me while i misunderstand the dev guide)

@rustbot

rustbot commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

Error: Cannot determine a new reviewer. Use r? <username or team> to request a specific reviewer or a team.

Please file an issue on GitHub at triagebot if there's a problem with this bot, or reach out on #triagebot on Zulip.

@kleinesfilmroellchen

Copy link
Copy Markdown
Contributor Author

Ah okay, so that doesn’t work here. Welp.

@tgross35

tgross35 commented Oct 7, 2026

Copy link
Copy Markdown
Member

No need to request reviews on this repo really, usually it's just me.

This is a really aggressive size optimization. memcpy is called everywhere, are people really going to want to save the 300 bytes for up a 4x slowdown in other parts of code? Maybe on targets that are severely flash-limited (@Patryk27 for AVR) but I suspect most users would consider keeping the word-size copies worth it.

@diondokter

Copy link
Copy Markdown
Member

Sometimes you really do care, yes. But this is indeed really aggressive. I wonder if it could be made in build-std that this is separately selectable instead of always on when core is built with optimize-for-size.

@kleinesfilmroellchen

kleinesfilmroellchen commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

On targets I am looking at, like the CH32V003 (16K Flash) and Pebble Original with STM32F205RE (24K combined memory), this is absolutely worth it. We’ve been looking at shaving off just a kilobyte here and there, and this makes a significant difference, especially since calls to these primitives are very common.

@tgross35

tgross35 commented Oct 7, 2026

Copy link
Copy Markdown
Member

It feels like perhaps we should have levels? I wonder why this is a feature at all #t-libs > optimize_for_size.

especially since calls to these primitives are very common.

That shouldn't matter, they should be getting instantiated once.

This hides the much slower versions of
memcpy/memset. The regular flag is still kept in
case it gets used in the future by other code.
@kleinesfilmroellchen

Copy link
Copy Markdown
Contributor Author

Added a more aggressive additional feature, in case that’s the direction we want to go.

@kleinesfilmroellchen kleinesfilmroellchen changed the title Optimize memset size Optimize memset/memcpy size Oct 7, 2026
@clarfonthey

Copy link
Copy Markdown
Contributor

Thank you!

@clarfonthey
clarfonthey merged commit 099953f into rust-lang:main Nov 6, 2026
47 checks passed
@kleinesfilmroellchen
kleinesfilmroellchen deleted the optimize-memset-size branch November 6, 2026 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants