anchao commented on PR #21340: URL: https://github.com/apache/nuttx/pull/21340#issuecomment-6731449770
> On these boards, this PR makes printf larger and uses more stack. The split is easier to read, but I think the community prefers the flash and the stack. > > Measured on the head [521f515](https://github.com/apache/nuttx/commit/521f515584cf02f3e5e195ecea9b47fecd2d2f44) against its base [9ffe762](https://github.com/apache/nuttx/commit/9ffe7625cb187004cf209f113b3cd96472c92ab2), `size nuttx`, with `-fstack-usage`. Boards: nucleo-f072rb:nsh (Cortex-M0), nucleo-f103rb:nsh (Cortex-M3), rv-virt:nsh (rv32), qemu-armv8a:nsh (arm64), each with its defconfig optimization (-Os); numbered arguments, locale and print extensions off. > > Image text: > > M0 M3 rv32 arm64 > float off +212 +200 +208 +332 > float on +232 +320 +264 +584 > float off, `vsprintf_put_field()` and `vsprintf_put_char()` plain `static` +84 +104 +114 +204 > float on, the same two `static` +96 +160 +160 +368 > Deepest stack from `lib_vsprintf()`, in bytes, base / head / the two helpers `static`: > > M0 M3 rv32 arm64 > float off 128 / 128 / 168 104 / 104 / 144 128 / 144 / 160 160 / 208 / 272 > float on 160 / 168 / 184 144 / 152 / 160 208 / 208 / 208 192 / 240 / 304 > So `static` removes 37% to 60% of the added flash, but then the stack grows more. The flash does not get back to the base on any board. > > The drop of the `vsprintf_internal()` frame shows only without optimization. On qemu-armv8a:nsh with float, numbered arguments, locale and print extensions on: 400 to 192 bytes at -O0, 224 to 224 at -Os, 256 to 272 at -O2. > > The printf series (#21493 and the PRs after it) changes most of this file. Fix: put this PR on hold until that series merges, then do the split on top of it, with no growth of image text and of the deepest stack on these boards. I can share the measurement scripts. @casaroli Thanks for checking this. I looked into this again, and I think the stack increase is related to the forced inlining. In NuttX, inline_function is defined as always_inline when optimization is enabled: #define inline_function __attribute__((always_inline)) inline So using static inline_function here forces GCC to inline all of these split helpers back into vsprintf_internal(). That can increase both the generated text and the caller's stack frame, because the local state from multiple helper paths is now combined in the same function. I tested this with GCC by removing inline_function from all of the split vsprintf helpers and keeping them as plain static functions. On my test config (gd32f450zk-eval / GCC, with CONFIG_LIBC_FLOATINGPOINT=n, CONFIG_LIBC_NUMBERED_ARGS=n and CONFIG_LIBC_LOCALE=n), the result was: nuttx.elf text: 173218 -> 171802 (-1416 bytes) lib_libvsprintf.o text: 4921 -> 3505 (-1416 bytes) stack usage: vsprintf_internal: 424 -> 192 bytes added helper frames: vsprintf_scan_literal 48 bytes vsprintf_put_field 40 bytes vsprintf_put_char 40 bytes vsprintf_put_integer 40 bytes vsprintf_pointer_flags 8 bytes So for this GCC configuration, removing forced inline is a net win: text size is smaller, and the deepest observed non-floating-point paths are also below the previous 424-byte vsprintf_internal frame. I updated the PR to drop inline_function from these helpers. Other configurations, especially floating-point / locale / numbered-args builds, may still have different call chains, so I am happy to re-check additional configs if needed. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
