ilog2: force inlining of __ilog2_u32() and __ilog2_u64()
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Wed, 23 Mar 2022 23:05:44 +0000 (16:05 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 24 Mar 2022 02:00:33 +0000 (19:00 -0700)
commitf334f5668bedf7307f6df1d98b14f55902931926
treeb4139b928db3e7084e0fdc97b3940db67853153a
parent14e83077d55ff4b88fe39f5e98fb8230c2ccb4fb
ilog2: force inlining of __ilog2_u32() and __ilog2_u64()

Building a kernel with CONFIG_CC_OPTIMISE_FOR_SIZE leads to
__ilog2_u32() being duplicated 50 times and __ilog2_u64() 3 times in
vmlinux on a tiny powerpc32 config.

__ilog2_u32() being 2 instructions it is not worth being kept out of
line, so force inlining.  Allthough the u64 version is a bit bigger,
there is still a small benefit in keeping it inlined.  On a 64 bits
config there's a real benefit.

With this change the size of vmlinux text is reduced by 1 kbytes, which
is approx 50% more than the size of the removed functions.

Before the patch there is for instance:

c00d2a94 <__ilog2_u32>:
c00d2a94: 7c 63 00 34  cntlzw  r3,r3
c00d2a98: 20 63 00 1f  subfic  r3,r3,31
c00d2a9c: 4e 80 00 20  blr

c00d36d8 <__order_base_2>:
c00d36d8: 28 03 00 01  cmplwi  r3,1
c00d36dc: 40 81 00 2c  ble     c00d3708 <__order_base_2+0x30>
c00d36e0: 94 21 ff f0  stwu    r1,-16(r1)
c00d36e4: 7c 08 02 a6  mflr    r0
c00d36e8: 38 63 ff ff  addi    r3,r3,-1
c00d36ec: 90 01 00 14  stw     r0,20(r1)
c00d36f0: 4b ff f3 a5  bl      c00d2a94 <__ilog2_u32>
c00d36f4: 80 01 00 14  lwz     r0,20(r1)
c00d36f8: 38 63 00 01  addi    r3,r3,1
c00d36fc: 7c 08 03 a6  mtlr    r0
c00d3700: 38 21 00 10  addi    r1,r1,16
c00d3704: 4e 80 00 20  blr
c00d3708: 38 60 00 00  li      r3,0
c00d370c: 4e 80 00 20  blr

With the patch it has become:

c00d356c <__order_base_2>:
c00d356c: 28 03 00 01  cmplwi  r3,1
c00d3570: 40 81 00 14  ble     c00d3584 <__order_base_2+0x18>
c00d3574: 38 63 ff ff  addi    r3,r3,-1
c00d3578: 7c 63 00 34  cntlzw  r3,r3
c00d357c: 20 63 00 20  subfic  r3,r3,32
c00d3580: 4e 80 00 20  blr
c00d3584: 38 60 00 00  li      r3,0
c00d3588: 4e 80 00 20  blr

No more need for __order_base_2() to setup a stack frame and
save/restore caller address. And the following 'add 1' is
merged in the subtract.

Another typical use of it:

c080ff28 <hugepagesz_setup>:
...
c080fff8: 7f c3 f3 78  mr      r3,r30
c080fffc: 4b 8f 81 f1  bl      c01081ec <__ilog2_u32>
c0810000: 38 63 ff f2  addi    r3,r3,-14
...

Becomes

c080ff1c <hugepagesz_setup>:
...
c080ffec: 7f c3 00 34  cntlzw  r3,r30
c080fff0: 20 63 00 11  subfic  r3,r3,17
...

Here no need to move r30 argument to r3 then substract 14 to result.  Just
work on r30 and merge the 'sub 14' with the 'sub from 31'.

Link: https://lkml.kernel.org/r/803a2ac3d923ebcfd0dd40f5886b05cae7bb0aba.1644243860.git.christophe.leroy@csgroup.eu
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/log2.h