Forced RVO in LFSR_CAT_* macros somehow

I think I'm understanding a bit more how RVO interacts with inline
functions. And by that I mean I'm learning that the way RVO interacts
with inline functions is unfortunately very cursed...

Just take a look at this diff. This change should be a noop. But somehow
it saves 200 bytes of RAM:

           code          stack
  before: 33684           2824
  after:  33664 (-0.1%)   2624 (-7.1%)

I think what's happening is passing the result of lfsr_data_from* into
lfsr_data_cat is somehow preventing RVO, because the parameter would
need to be copied into the right argument slot? (argument registers?)

But we really don't need a copy, because lfsr_data_cat should end up
inlined. By inserting a compound literal, we force RVO, and all of these
unnecessary copies get cleaned up after lfsr_data_cat is inlined.

Keep in mind, in a perfect world, lfsr_data_cat should be a noop.

But I could be wrong about all of this. It's not really clear what the
compiler is doing, and I haven't dived that far into the disassembly...
This commit is contained in:
Christopher Haster
2024-05-09 17:34:13 -05:00
parent 250c1dd57e
commit f39057d2e1
+13 -12
View File
@@ -1502,12 +1502,12 @@ static inline lfs_size_t lfsr_cat_size(lfsr_cat_t cat) {
#define LFSR_LLEB128_DSIZE 4
#define LFSR_CAT_LEB128(_word) \
lfsr_data_cat( \
lfsr_data_fromleb128(_word, (uint8_t[LFSR_LEB128_DSIZE]){0}))
lfsr_data_cat(*(lfsr_data_t[1]){ \
lfsr_data_fromleb128(_word, (uint8_t[LFSR_LEB128_DSIZE]){0})})
#define LFSR_CAT_LLEB128(_word) \
lfsr_data_cat( \
lfsr_data_fromlleb128(_word, (uint8_t[LFSR_LLEB128_DSIZE]){0}))
lfsr_data_cat(*(lfsr_data_t[1]){ \
lfsr_data_fromlleb128(_word, (uint8_t[LFSR_LLEB128_DSIZE]){0})})
static inline lfsr_data_t lfsr_data_fromleb128(uint32_t word,
uint8_t buffer[static LFSR_LEB128_DSIZE]) {
@@ -1830,7 +1830,7 @@ typedef struct lfsr_ecksum {
#define LFSR_ECKSUM_DSIZE (4+4)
#define LFSR_CAT_ECKSUM_(_ecksum, _buffer) \
lfsr_data_cat(lfsr_data_fromecksum(_ecksum, _buffer))
lfsr_data_cat(*(lfsr_data_t[1]){lfsr_data_fromecksum(_ecksum, _buffer)})
#define LFSR_CAT_ECKSUM(_ecksum) \
LFSR_CAT_ECKSUM_(_ecksum, (uint8_t[LFSR_ECKSUM_DSIZE]){0})
@@ -1887,7 +1887,7 @@ static int lfsr_data_readecksum(lfs_t *lfs, lfsr_data_t *data,
#define LFSR_BPTR_DSIZE (4+5+4+4+4)
#define LFSR_CAT_BPTR_(_bptr, _buffer) \
lfsr_data_cat(lfsr_data_frombptr(_bptr, _buffer))
lfsr_data_cat(*(lfsr_data_t[1]){lfsr_data_frombptr(_bptr, _buffer)})
#define LFSR_CAT_BPTR(_bptr) \
LFSR_CAT_BPTR_(_bptr, (uint8_t[LFSR_BPTR_DSIZE]){0})
@@ -2099,7 +2099,7 @@ static inline bool lfsr_grm_isrm(const lfsr_grm_t *grm, lfsr_smid_t mid) {
}
#define LFSR_CAT_GRM_(_grm, _buffer) \
lfsr_data_cat(lfsr_data_fromgrm(_grm, _buffer))
lfsr_data_cat(*(lfsr_data_t[1]){lfsr_data_fromgrm(_grm, _buffer)})
#define LFSR_CAT_GRM(_grm) \
LFSR_CAT_GRM_(_grm, (uint8_t[LFSR_GRM_DSIZE]){0})
@@ -4170,7 +4170,7 @@ static inline int lfsr_btree_cmp(
#define LFSR_BRANCH_DSIZE (5+4+4)
#define LFSR_CAT_BRANCH_(_branch, _buffer) \
lfsr_data_cat(lfsr_data_frombranch(_branch, _buffer))
lfsr_data_cat(*(lfsr_data_t[1]){lfsr_data_frombranch(_branch, _buffer)})
#define LFSR_CAT_BRANCH(_branch) \
LFSR_CAT_BRANCH_(_branch, (uint8_t[LFSR_BRANCH_DSIZE]){0})
@@ -4243,7 +4243,7 @@ static int lfsr_data_readbranch(lfs_t *lfs, lfsr_data_t *data,
#define LFSR_BTREE_DSIZE (5+LFSR_BRANCH_DSIZE)
#define LFSR_CAT_BTREE_(_btree, _buffer) \
lfsr_data_cat(lfsr_data_frombtree(_btree, _buffer))
lfsr_data_cat(*(lfsr_data_t[1]){lfsr_data_frombtree(_btree, _buffer)})
#define LFSR_CAT_BTREE(_btree) \
LFSR_CAT_BTREE_(_btree, (uint8_t[LFSR_BTREE_DSIZE]){0})
@@ -5314,7 +5314,7 @@ static inline int lfsr_shrub_cmp(
#define LFSR_SHRUB_DSIZE (5+4)
#define LFSR_CAT_SHRUB_(_rbyd, _buffer) \
lfsr_data_cat(lfsr_data_fromshrub(_rbyd, _buffer))
lfsr_data_cat(*(lfsr_data_t[1]){lfsr_data_fromshrub(_rbyd, _buffer)})
#define LFSR_CAT_SHRUB(_rbyd) \
LFSR_CAT_SHRUB_(_rbyd, (uint8_t[LFSR_SHRUB_DSIZE]){0})
@@ -5519,7 +5519,7 @@ static inline bool lfsr_mptr_ismrootanchor(const lfsr_mptr_t *mptr) {
#define LFSR_MPTR_DSIZE (5+5)
#define LFSR_CAT_MPTR_(_mptr, _buffer) \
lfsr_data_cat(lfsr_data_frommptr(_mptr, _buffer))
lfsr_data_cat(*(lfsr_data_t[1]){lfsr_data_frommptr(_mptr, _buffer)})
#define LFSR_CAT_MPTR(_mptr) \
LFSR_CAT_MPTR_(_mptr, (uint8_t[LFSR_MPTR_DSIZE]){0})
@@ -8113,7 +8113,8 @@ typedef struct lfsr_geometry {
#define LFSR_GEOMETRY_DSIZE (4+5)
#define LFSR_CAT_GEOMETRY_(_geometry, _buffer) \
lfsr_data_cat(lfsr_data_fromgeometry(_geometry, _buffer))
lfsr_data_cat(*(lfsr_data_t[1]){ \
lfsr_data_fromgeometry(_geometry, _buffer)})
#define LFSR_CAT_GEOMETRY(_geometry) \
LFSR_CAT_GEOMETRY_(_geometry, (uint8_t[LFSR_GEOMETRY_DSIZE]){0})