Testing LFSR_ATTR as a static inline function

I'm committing this temporarily mostly just to record some _very_
interesting code/stack measurements.

This explores replacing the LFSR_ATTR macro with an inline function that
does the same thing:

  #define LFSR_ATTR(_tag, _delta, _cat) \
      ((const lfsr_attr_t){_tag, _delta, _cat})

vs:

  #define LFSR_ATTR(_tag, _delta, _cat) \
      lfsr_attr(_tag, _delta, _cat)

  static inline lfsr_attr_t lfsr_attr(
          lfsr_tag_t tag, lfsr_srid_t delta, lfsr_cat_t cat) {
      return (lfsr_attr_t){tag, delta, cat};
  }

The motivation for this is to eventually support more complex
lfsr_attr_t layouts. Specifically, it would be nice if we could break up
the lfsr_cat_t into separate size/ptr fields. Unfortunately we can't
declare temporaries in macros (I wish we had statement expressions), and
we really don't want to duplicate the entire cat tree, so an inline
function seems like the only way to accomplish this...

But static inline functions have the same cost as a macro you say?

No. This assumes a perfect compiler. And it's pretty unfair to compiler
developers to expect a perfect compiler.

To be fair, this is an extremely harsh test. We use LFSR_ATTR _heavily_,
which is why it's getting this much scrutiny. lfsr_attr also both takes
in a 2-word struct, and returns a _4_-word struct, which probably makes
things messy.

Still, the results are concerning:

                  code          stack
  macro:         33672           2776
  inline:        34512 (+2.5%)   2952 (+6.3%)
  always_inline: 34512 (+2.5%)   2952 (+6.3%)
  noinline:      33920 (+0.7%)   2888 (+4.0%)

Measured with GCC 11 -mthumb -Os. I also measured with
__attribute__((always_inline/noinline)) just to see how that affected
things.
This commit is contained in:
Christopher Haster
2024-05-07 13:25:22 -05:00
parent 010c82475f
commit e4069ee4fc
+6 -1
View File
@@ -1567,7 +1567,12 @@ typedef struct lfsr_attr {
} lfsr_attr_t;
#define LFSR_ATTR(_tag, _delta, _cat) \
((const lfsr_attr_t){_tag, _delta, _cat})
lfsr_attr(_tag, _delta, _cat)
static inline lfsr_attr_t lfsr_attr(
lfsr_tag_t tag, lfsr_srid_t delta, lfsr_cat_t cat) {
return (lfsr_attr_t){tag, delta, cat};
}
#define LFSR_ATTR_NOOP() LFSR_ATTR(LFSR_TAG_NULL, 0, LFSR_CAT_NULL())