include/linux/container_of.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
This series refactors the container_of() function-like macro to improve
readability and remove a sparse/W=2 shadow warning. Further details in
each patch.
While I was expecting this series to be boring and purely cosmetic, the
bloat-o-meter stats gave some unexpected results:
$ ./scripts/bloat-o-meter vmlinux7.2-rc3_before.o vmlinux7.2-rc3_after.o
add/remove: 0/0 grow/shrink: 133/93 up/down: 5914901/-14344137 (-8429236)
< ... 227 lines redacted >
Total: Before=2641674349, After=2633245113, chg -0.32%
(done on v7.2-rc3 with GCC 15.3.0 on an x86_64 defconfig)
Upon analysis, this change in size can be tracked down to places where
container_of() is used in combination with __builtin_constant_p().
Here is a minimal reproducer:
struct foo {
int a;
};
#define to_foo(a_ptr) container_of(a_ptr, struct foo, a)
int f(int *a)
{
return __builtin_constant_p(to_foo(a)->a) || a;
}
The assembly code before this series...:
xor eax, eax
test rdi, rdi
setne al
ret
...and after:
mov eax, 1
ret
Link: https://godbolt.org/z/fenbGexjY
__builtin_constant_p(to_foo(a)->a) evaluates to false but gives the
optimiser the hint that pointer a is not NULL because of the
assumption that no undefined behaviour occurs. With this, the
expression:
__builtin_constant_p(to_foo(a)->a) || a
could be evaluated as true by the optimiser.
But the small variation in container_of() makes it that the optimiser
currently misses this optimisation but manages to do it after the
simplification of patch #3 of this series.
When __builtin_constant_p()'s argument is not trivially a compile time
constant, the result of __builtin_constant_p() comes late in the
evaluation process. And if it comes too late, after some other
optimisations were already done, the compiler will not retry and simply
miss these optimisations.
Note that the above example is very fragile and the results shown in
the godbolt link might not be reproducible under very small
variations.
Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
---
Vincent Mailhol (3):
container_of: apply typeof_member() to container_of()
container_of: remove useless pair of parentheses
container_of: remove local __mptr variable
include/linux/container_of.h | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
---
base-commit: a13c140cc289c0b7b3770bce5b3ad42ab35074aa
change-id: 20260110-containerof_refactor-63acf8118a18
Best regards,
--
Vincent Mailhol <mailhol@kernel.org>
On Tue, Jul 14, 2026 at 08:18:00PM +0200, Vincent Mailhol wrote:
> This series refactors the container_of() function-like macro to improve
> readability and remove a sparse/W=2 shadow warning. Further details in
> each patch.
>
> While I was expecting this series to be boring and purely cosmetic, the
> bloat-o-meter stats gave some unexpected results:
>
> $ ./scripts/bloat-o-meter vmlinux7.2-rc3_before.o vmlinux7.2-rc3_after.o
> add/remove: 0/0 grow/shrink: 133/93 up/down: 5914901/-14344137 (-8429236)
> < ... 227 lines redacted >
> Total: Before=2641674349, After=2633245113, chg -0.32%
>
> (done on v7.2-rc3 with GCC 15.3.0 on an x86_64 defconfig)
>
> Upon analysis, this change in size can be tracked down to places where
> container_of() is used in combination with __builtin_constant_p().
>
> Here is a minimal reproducer:
>
> struct foo {
> int a;
> };
>
> #define to_foo(a_ptr) container_of(a_ptr, struct foo, a)
>
> int f(int *a)
> {
> return __builtin_constant_p(to_foo(a)->a) || a;
> }
>
> The assembly code before this series...:
>
> xor eax, eax
> test rdi, rdi
> setne al
> ret
>
> ...and after:
>
> mov eax, 1
> ret
>
> Link: https://godbolt.org/z/fenbGexjY
>
> __builtin_constant_p(to_foo(a)->a) evaluates to false but gives the
> optimiser the hint that pointer a is not NULL because of the
> assumption that no undefined behaviour occurs. With this, the
> expression:
>
> __builtin_constant_p(to_foo(a)->a) || a
>
> could be evaluated as true by the optimiser.
>
> But the small variation in container_of() makes it that the optimiser
> currently misses this optimisation but manages to do it after the
> simplification of patch #3 of this series.
>
> When __builtin_constant_p()'s argument is not trivially a compile time
> constant, the result of __builtin_constant_p() comes late in the
> evaluation process. And if it comes too late, after some other
> optimisations were already done, the compiler will not retry and simply
> miss these optimisations.
>
> Note that the above example is very fragile and the results shown in
> the godbolt link might not be reproducible under very small
> variations.
>
> Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
"fun" thing is, clang gets this right without your change, so this only
seems to help the gcc users.
Anyway, very nice optimizations, thanks for this! I'll queue these up
later today.
greg k-h
On 15/07/2026 at 06:54, Greg Kroah-Hartman wrote:
> On Tue, Jul 14, 2026 at 08:18:00PM +0200, Vincent Mailhol wrote:
>> This series refactors the container_of() function-like macro to improve
>> readability and remove a sparse/W=2 shadow warning. Further details in
>> each patch.
>>
>> While I was expecting this series to be boring and purely cosmetic, the
>> bloat-o-meter stats gave some unexpected results:
>>
>> $ ./scripts/bloat-o-meter vmlinux7.2-rc3_before.o vmlinux7.2-rc3_after.o
>> add/remove: 0/0 grow/shrink: 133/93 up/down: 5914901/-14344137 (-8429236)
>> < ... 227 lines redacted >
>> Total: Before=2641674349, After=2633245113, chg -0.32%
>>
>> (done on v7.2-rc3 with GCC 15.3.0 on an x86_64 defconfig)
>>
>> Upon analysis, this change in size can be tracked down to places where
>> container_of() is used in combination with __builtin_constant_p().
>>
>> Here is a minimal reproducer:
>>
>> struct foo {
>> int a;
>> };
>>
>> #define to_foo(a_ptr) container_of(a_ptr, struct foo, a)
>>
>> int f(int *a)
>> {
>> return __builtin_constant_p(to_foo(a)->a) || a;
>> }
>>
>> The assembly code before this series...:
>>
>> xor eax, eax
>> test rdi, rdi
>> setne al
>> ret
>>
>> ...and after:
>>
>> mov eax, 1
>> ret
>>
>> Link: https://godbolt.org/z/fenbGexjY
>>
>> __builtin_constant_p(to_foo(a)->a) evaluates to false but gives the
>> optimiser the hint that pointer a is not NULL because of the
>> assumption that no undefined behaviour occurs. With this, the
>> expression:
>>
>> __builtin_constant_p(to_foo(a)->a) || a
>>
>> could be evaluated as true by the optimiser.
>>
>> But the small variation in container_of() makes it that the optimiser
>> currently misses this optimisation but manages to do it after the
>> simplification of patch #3 of this series.
>>
>> When __builtin_constant_p()'s argument is not trivially a compile time
>> constant, the result of __builtin_constant_p() comes late in the
>> evaluation process. And if it comes too late, after some other
>> optimisations were already done, the compiler will not retry and simply
>> miss these optimisations.
>>
>> Note that the above example is very fragile and the results shown in
>> the godbolt link might not be reproducible under very small
>> variations.
>>
>> Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
>
> "fun" thing is, clang gets this right without your change, so this only
> seems to help the gcc users.
Indeed. I forgot to mention it, but I also observed that clang is not
impacted by these weird __builtin_constant_p() intricacies.
One lesson learned it that in GCC __builtin_constant_p() can become an
optimisation killer.
> Anyway, very nice optimizations, thanks for this! I'll queue these up
> later today.
Thanks!
Yours sincerely,
Vincent Mailhol
© 2016 - 2026 Red Hat, Inc.