xmb: keep the messagebox and background draw phases out of line

Same treatment as rgui_render and ozone_frame.  xmb_frame() is
factored into named phases and the single-call-site ones are inlined
back into it at -O3.

  xmb_frame        .text   20496 -> 15818   (-23%)
                   spills    827 ->   590
                   frame     9472 ->  3608

  broken out       xmb_render_messagebox_internal   3804
                   xmb_draw_bg                      1115

The frame drop is the messagebox scratch, which was being charged to
every frame rather than only to frames that draw a messagebox.

XMB_NOINLINE moves to the top of the file so it is visible at
xmb_render_messagebox_internal's definition, and its comment is
extended to cover this second use.

Only these two are annotated.  Measured individually,
xmb_draw_fullscreen_thumbnails makes xmb_frame *larger* when outlined
(22242, +1759), xmb_draw_dark_layer is worth 23 bytes for 368 bytes of
TU growth, and xmb_draw_no_thumbnail_available was not being inlined
into xmb_frame in the first place.  All three are left alone.

TU .text is 95316 -> 95332, i.e. flat; the code is moved, not copied.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-07-27 10:18:27 +02:00
1 parent a5217ab0d1
commit f55e41d216
1 file changed
+27 -20
+27 -20
View File
@@ -63,6 +63,31 @@
#include "../../cheevos/cheevos_menu.h"
#endif
/* Force a helper out of line even though it has a single call site.
*
* Follows the RXML_NOINLINE precedent in
* libretro-common/formats/xml/rxml.c.
*
* Two reasons it is needed here. An inlined helper's stack slots are
* charged to the caller's frame on every call, whether or not the
* helper's branch is taken, which matters on the per-entry draw path.
* And xmb_frame() is already factored into named phases, but the ones
* called exactly once get inlined straight back into it, so branches
* that are not taken on a given frame still occupy the fall-through
* path in L1i.
*
* Under -Os the compiler already optimises for size and the forced
* outlining only adds call overhead, so it is disabled there. */
#if defined(__OPTIMIZE_SIZE__)
#define XMB_NOINLINE
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
#define XMB_NOINLINE __attribute__((noinline))
#elif defined(_MSC_VER)
#define XMB_NOINLINE __declspec(noinline)
#else
#define XMB_NOINLINE
#endif
#define XMB_RIBBON_ROWS (64)
#define XMB_RIBBON_COLS (64)
#define XMB_RIBBON_VERTICES (XMB_RIBBON_ROWS * (2 * XMB_RIBBON_COLS)) - (2 * XMB_RIBBON_COLS)
@@ -1233,7 +1258,7 @@ static void xmb_messagebox(void *data, const char *message)
}
}
static void xmb_render_messagebox_internal(
XMB_NOINLINE static void xmb_render_messagebox_internal(
void *userdata,
gfx_display_t *p_disp,
gfx_display_ctx_driver_t *dispctx,
@@ -5560,24 +5585,6 @@ typedef struct
bool shadows_enable;
} xmb_draw_ctx_t;
/* Force a helper out of line even though it has a single call site.
*
* Follows the RXML_NOINLINE precedent in
* libretro-common/formats/xml/rxml.c. Used below for the per-entry
* draw path, where an inlined helper's stack slots are charged to the
* caller's frame on every call regardless of whether the helper's
* branch is taken. Under -Os the outlining only adds call overhead,
* so it is disabled there. */
#if defined(__OPTIMIZE_SIZE__)
#define XMB_NOINLINE
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
#define XMB_NOINLINE __attribute__((noinline))
#elif defined(_MSC_VER)
#define XMB_NOINLINE __declspec(noinline)
#else
#define XMB_NOINLINE
#endif
/* Sublabel rendering for the selected entry.
*
* Split out of xmb_draw_item() rather than left inline: the block owns
@@ -8213,7 +8220,7 @@ static void xmb_render(void *data,
GFX_ANIMATION_CLEAR_ACTIVE(p_anim);
}
static void xmb_draw_bg(
XMB_NOINLINE static void xmb_draw_bg(
void *userdata,
gfx_display_t *p_disp,
gfx_display_ctx_driver_t *dispctx,