Re: [PATCH] arm64/io: add constant-argument check

From: Arnd Bergmann
Date: Wed May 29 2024 - 08:30:08 EST


On Wed, May 29, 2024, at 13:14, Mark Rutland wrote:
>> {
>> - if (count == 8 || count == 4 || count == 2 || count == 1) {
>> + if (__builtin_constant_p(count) &&
>> + (count == 8 || count == 4 || count == 2 || count == 1)) {
>> __const_memcpy_toio_aligned32(to, from, count);
>> dgh();
>> } else {
>
> I don't think this is the right fix.
>
> The idea was that this was checked in __iowrite32_copy(), which does:
>
> #define __iowrite32_copy(to, from, count) \
> (__builtin_constant_p(count) ? \
> __const_iowrite32_copy(to, from, count) : \
> __iowrite32_copy_full(to, from, count))
>
> ... and so __const_iowrite32_copy() should really be marked as __always_inline,
> and the same for __const_memcpy_toio_aligned32(), to guarantee that both get
> inlined and such that __const_memcpy_toio_aligned32() sees a constant.
>
> The same reasoning applies to __const_iowrite64_copy() and
> __const_memcpy_toio_aligned64().
>
> Checking for a constant in __const_iowrite32_copy() doesn't guarantee
> that __const_memcpy_toio_aligned32() is inlined and will actually see a
> constant.
>
> Does diff the below you for you?

Yes, your version addresses both failures I ran into, and
I think all other theoretical cases.

I would prefer to combine both though, using __always_inline
to force the compiler to pick the inline version over
__iowrite32_copy_full() even when it is optimizing for size
and it decides the inline version is larger, but removing
the extra complexity from the macro.

According to Jason, he used a macro here to be sure
that the compiler can detect an inline function argument
as constant when the value is known but it is not
a constant value according to the C standard.

This was indeed a problem in older versions of clang
that missed a lot of optimizations in the kernel, but
clang-8 and higher were changed to have the same behavior
as gcc here, so it is no longer necessary now that the
older versions are unable to build kernels.

Arnd