[PATCH v2 2/3] common: board: make initcalls static
Jerome Forissier
jerome.forissier at linaro.org
Mon Jan 27 11:32:25 CET 2025
On 1/25/25 00:58, Marek Vasut wrote:
> On 1/24/25 6:23 PM, Jerome Forissier wrote:
>>
>>
>> On 1/24/25 17:23, Marek Vasut wrote:
>>> On 1/24/25 4:57 PM, Jerome Forissier wrote:
>>>>
>>>>
>>>> On 1/24/25 11:35, Marek Vasut wrote:
>>>>> On 1/24/25 10:10 AM, Jerome Forissier wrote:
>>>>>> +#define INITCALL(_call) \
>>>>>> + do { \
>>>>>> + if (_call()) { \
>>>>>> + printf("%s(): initcall %s() failed\n", __func__, \
>>>>>> + #_call); \
>>>>>> + hang(); \
>>>>>> + } \
>>>>>> + } while (0)
>>>>>
>>>>> Can this be turned into some static inline function too , so typechecking would be retained ? Maybe the function can be passed in a function pointer to call ?
>>>>
>>>>
>>>> Doing the below totally kills the space gain (-160 bytes instead of -2281
>>>> on zynqmp_kria_defconfig, with LTO).
>>>
>>> Does the compiler not inline the functions perhaps ?
>>
>> It does. inline vs __always_inline makes no difference. The assembly
>> code is pretty difficult to understand in any case (macro or static
>> inline function). There are pieces of called functions all over the
>> place inside initcall_run_f() which is to be expected with LTO I
>> suppose.
>>
>>>
>>>> And it prevents from printing the
>>>> function name in case of error, which is nicer than an address
>>>> (especially with relocation at play).
>>> That function name can be passed in using __func__ as a parameter.
>>
>> True. That being said, the type-checking argument does not seem
>> decisive here, and although I too prefer to use static inline
>> functions over macros when possible, it looks like we have no choice
>> in this case.
> Can you try this kind of thing (might need some tweaking):
>
> "
> static void check_and_fail(int *ret) {
> if (*ret) {
> printf("failed\n");
> hang();
> }
> }
>
> static inline void INITCALL(int (*_call)(void))
> {
> int ret __attribute__((__cleanup__(check_and_fail))) = _call();
> }
> "
>
> (maybe it really is the passing of pointer to _call() function into the INITCALL() function which confuses gcc into not inlining this right, but let's find out)
It seems to be working as expected (size-wise). Comparing the macro
version with yours, without LTO then with LTO:
$ ../linux/scripts/bloat-o-meter /tmp/u-boot.macro /tmp/u-boot.inlinefn
add/remove: 2/0 grow/shrink: 1/2 up/down: 1386/-1700 (-314)
Function old new delta
initcall_run_f - 1316 +1316
check_and_fail.isra - 64 +64
version_string 70 76 +6
board_init_r 836 664 -172
board_init_f 1572 44 -1528
Total: Before=1121213, After=1120899, chg -0.03%
$ ../linux/scripts/bloat-o-meter /tmp/u-boot.macro.lto /tmp/u-boot.inlinefn.lto
add/remove: 5/3 grow/shrink: 2/3 up/down: 11418/-11072 (346)
Function old new delta
initcall_run_r - 7532 +7532
initcall_run_f - 3540 +3540
add_to_list.lto_priv - 248 +248
zynqmp_power - 48 +48
check_and_fail.isra - 32 +32
__func__ 975 987 +12
version_string 70 76 +6
__func__.lto_priv 3700 3688 -12
zynqmp_power.lto_priv 48 - -48
add_to_list 248 - -248
get_mem_top 568 - -568
board_init_f 2880 56 -2824
board_init_r 7424 52 -7372
Total: Before=1068190, After=1068536, chg +0.03%
But note that the two are not equivalent since yours doesn't print
the initcall name in case of failure.
Regards,
--
Jerome
More information about the U-Boot
mailing list