[patch] x86: phase out forced inlining

Ingo Molnar
2008-03-03T12:13:56Z

* Ingo Molnar <mingo@elte.hu> wrote:

> > > no, what we should nuke is this always_inline definition. That was
> > > always the intention of FORCED_INLINE, and the removal of
> > > FORCED_INLINE was to _remove the forcing_, not to make it
> > > unconditional.
> >
> > It was always unconditional, and neither adding, toggling nor
> > removing of CONFIG_FORCED_INLINING changed this invariant.
> >
> > And what we should do is to attack the excessive wrong usage of
> > inlines in .c files, not messing with a global #define in a way that
> > the results on 24 architectures with 7 different releases of gcc
> > would be unpredictable.
>
> i see, so you never properly reported and fixed it because you prefer
> a 1000 small crappy changes over one change. You could have
> significantly contributed to truly making Linux smaller, but you
> decided not to do it.
>
> and i disagree with your notion that flipping it around is risky in
> any unacceptable or unmanageable way. It has far less risks on the
> compiler than say CONFIG_CC_OPTIMIZE_FOR_SIZE. It has far less risks
> than changing to a new compiler version. Why you think it's
> "unpredictable" is a mystery to me.
>
> It almost seems to me you were happy with having that bug in the
> kernel? Please tell me that i'm wrong about that impression!
>
> i'll reinstate this .config option and let it do the right thing.
> Forced inlining was supposed to be _phased out_, not phased in.

i just implemented the trivial fix below and it gave me a massive, 2.3%
text size reduction (!) on a typical .config. That's more than 120K
shaved off the vmlinux.

Why, despite being aware of this bug, you never fixed this properly is a
mystery to me - this is more .text size savings than you have done so
far with all your uninlining patches of the past few years combined, and
it's probably more than you could have achieved in the next 5 years.

Ingo

---------------------->
Subject: x86: phase out forced inlining
From: Ingo Molnar <mingo@elte.hu>
Date: Mon Mar 03 12:38:52 CET 2008

allow gcc to optimize the kernel image's size by uninlining
functions that have been marked 'inline'. Previously gcc was
forced by Linux to always-inline these functions via a gcc
attribute:

#define inline inline __attribute__((always_inline))

Especially when the user has already selected
CONFIG_OPTIMIZE_FOR_SIZE=y this can make a huge difference in
kernel image size (using a standard Fedora .config):

text data bss dec hex filename
5613924 562708 3854336 10030968 990f78 vmlinux.before
5486689 562708 3854336 9903733 971e75 vmlinux.after

that's a 2.3% text size reduction (!).

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
arch/x86/Kconfig.debug | 13 +++++++++++++
arch/x86/configs/i386_defconfig | 1 +
arch/x86/configs/x86_64_defconfig | 1 +
include/linux/compiler-gcc.h | 12 +++++++++---
4 files changed, 24 insertions(+), 3 deletions(-)

Index: linux-x86.q/arch/x86/Kconfig.debug
===================================================================
--- linux-x86.q.orig/arch/x86/Kconfig.debug
+++ linux-x86.q/arch/x86/Kconfig.debug
@@ -336,3 +336,16 @@ config CPA_DEBUG
Do change_page_attr() self-tests every 30 seconds.

endmenu
+
+config OPTIMIZE_INLINING
+ bool "Allow gcc to uninline functions marked 'inline'"
+ default y
+ help
+ This option determines if the kernel forces gcc to inline the functions
+ developers have marked 'inline'. Doing so takes away freedom from gcc to
+ do what it thinks is best, which is desirable for the gcc 3.x series of
+ compilers. The gcc 4.x series have a rewritten inlining algorithm and
+ disabling this option will generate a smaller kernel there. Hopefully
+ this algorithm is so good that allowing gcc4 to make the decision can
+ become the default in the future, until then this option is there to
+ test gcc for this.
Index: linux-x86.q/arch/x86/configs/i386_defconfig
===================================================================
--- linux-x86.q.orig/arch/x86/configs/i386_defconfig
+++ linux-x86.q/arch/x86/configs/i386_defconfig
@@ -1421,6 +1421,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_FRAME_POINTER is not set
+CONFIG_OPTIMIZE_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
Index: linux-x86.q/arch/x86/configs/x86_64_defconfig
===================================================================
--- linux-x86.q.orig/arch/x86/configs/x86_64_defconfig
+++ linux-x86.q/arch/x86/configs/x86_64_defconfig
@@ -1346,6 +1346,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_FRAME_POINTER is not set
+CONFIG_OPTIMIZE_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
Index: linux-x86.q/include/linux/compiler-gcc.h
===================================================================
--- linux-x86.q.orig/include/linux/compiler-gcc.h
+++ linux-x86.q/include/linux/compiler-gcc.h
@@ -28,9 +28,15 @@
#define __must_be_array(a) \
BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))

-#define inline inline __attribute__((always_inline))
-#define __inline__ __inline__ __attribute__((always_inline))
-#define __inline __inline __attribute__((always_inline))
+/*
+ * Force always-inline if the user requests it so via the .config:
+ */
+#ifndef CONFIG_OPTIMIZE_INLINING
+# define inline inline __attribute__((always_inline))
+# define __inline__ __inline__ __attribute__((always_inline))
+# define __inline __inline __attribute__((always_inline))
+#endif
+
#define __deprecated __attribute__((deprecated))
#define __packed __attribute__((packed))
#define __weak __attribute__((weak))