From b5515692062b50e592c3c6e625170406b4ce5c45 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 5 Feb 2025 01:08:19 -0600 Subject: [PATCH] Adopted LFS_FORCEINLINE May revisit this in the future, but this is the best solution I can think of right now, that doesn't run into duplicate macro-argument side-effect issues... Statement expressions would be another solution, but that's even less portable! At the moment this is only used for functions that implement LFSR_DATA_* and LFSR_RAT_* macros. These _need_ to be inlined to avoid a large code-size explosion, and GCC seems to have issues with this. For most of the other inlinable functions, relying on C99's inline + compiler heuristics seems to be fine. Code changes: before: 36304 2576 640 no-forceinline: 36460 (+0.4%) 2664 (+3.4%) 640 (+0.0%) yes-forceinline: 36300 (-0.0%) 2576 (+0.0%) 640 (+0.0%) --- lfs.c | 20 +++++++++++--------- lfs_util.h | 10 ++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/lfs.c b/lfs.c index 84f48da2..8f72164f 100644 --- a/lfs.c +++ b/lfs.c @@ -1663,8 +1663,10 @@ static inline lfs_size_t lfsr_data_size(lfsr_data_t data) { } // data slicing -// TODO what to do about this inlining situation? -__attribute__((always_inline)) +#define LFSR_DATA_SLICE(_data, _off, _size) \ + ((struct {lfsr_data_t d;}){lfsr_data_fromslice(_data, _off, _size)}.d) + +LFS_FORCEINLINE static inline lfsr_data_t lfsr_data_fromslice(lfsr_data_t data, lfs_ssize_t off, lfs_ssize_t size) { // limit our off/size to data range, note the use of unsigned casts @@ -1690,17 +1692,19 @@ static inline lfsr_data_t lfsr_data_fromslice(lfsr_data_t data, return data; } -#define LFSR_DATA_SLICE(_data, _off, _size) \ - ((struct {lfsr_data_t d;}){lfsr_data_fromslice(_data, _off, _size)}.d) +#define LFSR_DATA_TRUNCATE(_data, _size) \ + ((struct {lfsr_data_t d;}){lfsr_data_fromtruncate(_data, _size)}.d) +LFS_FORCEINLINE static inline lfsr_data_t lfsr_data_fromtruncate(lfsr_data_t data, lfs_size_t size) { return LFSR_DATA_SLICE(data, -1, size); } -#define LFSR_DATA_TRUNCATE(_data, _size) \ - ((struct {lfsr_data_t d;}){lfsr_data_fromtruncate(_data, _size)}.d) +#define LFSR_DATA_FRUNCATE(_data, _size) \ + ((struct {lfsr_data_t d;}){lfsr_data_fromfruncate(_data, _size)}.d) +LFS_FORCEINLINE static inline lfsr_data_t lfsr_data_fromfruncate(lfsr_data_t data, lfs_size_t size) { return LFSR_DATA_SLICE(data, @@ -1710,9 +1714,6 @@ static inline lfsr_data_t lfsr_data_fromfruncate(lfsr_data_t data, -1); } -#define LFSR_DATA_FRUNCATE(_data, _size) \ - ((struct {lfsr_data_t d;}){lfsr_data_fromfruncate(_data, _size)}.d) - // macros for le32/leb128/lleb128 encoding, these are useful for // building rats @@ -2023,6 +2024,7 @@ typedef struct lfsr_rat { #define LFSR_RAT(_tag, _weight, _data) \ ((struct {lfsr_rat_t a;}){lfsr_rat(_tag, _weight, _data)}.a) +LFS_FORCEINLINE static inline lfsr_rat_t lfsr_rat( lfsr_tag_t tag, lfsr_srid_t weight, lfsr_data_t data) { // only simple data works here diff --git a/lfs_util.h b/lfs_util.h index 79d9ebc8..b46eaff3 100644 --- a/lfs_util.h +++ b/lfs_util.h @@ -229,6 +229,16 @@ extern "C" #endif +// Some function attributes, no way around these + +// Force a function to be inlined +#if !defined(LFS_NO_BUILTINS) && defined(__GNUC__) +#define LFS_FORCEINLINE __attribute__((always_inline)) +#else +#define LFS_FORCEINLINE +#endif + + // Builtin functions, these may be replaced by more efficient // toolchain-specific implementations. LFS_NO_BUILTINS falls back to a more // expensive basic C implementation for debugging purposes