Skip to content

Commit a586df0

Browse files
Andi KleenLinus Torvalds
authored andcommitted
x86: Support __attribute__((__cold__)) in gcc 4.3
gcc 4.3 supports a new __attribute__((__cold__)) to mark functions cold. Any path directly leading to a call of this function will be unlikely. And gcc will try to generate smaller code for the function itself. Please use with care. The code generation advantage isn't large and in most cases it is not worth uglifying code with this. This patch marks some common error functions like panic(), printk() as cold. This will longer term make many unlikely()s unnecessary, although we can keep them for now for older compilers. BUG is not marked cold because there is currently no way to tell gcc to mark a inline function told. Also all __init and __exit functions are marked cold. With a non -Os build this will tell the compiler to generate slightly smaller code for them. I think it currently only uses less alignments for labels, but that might change in the future. One disadvantage over *likely() is that they cannot be easily instrumented to verify them. Another drawback is that only the latest gcc 4.3 snapshots support this. Unfortunately we cannot detect this using the preprocessor. This means older snapshots will fail now. I don't think that's a problem because they are unreleased compilers that nobody should be using. gcc also has a __hot__ attribute, but I don't see any sense in using this in the kernel right now. But someday I hope gcc will be able to use more aggressive optimizing for hot functions even in -Os, if that happens it should be added. Includes compile fix from Thomas Gleixner. Cc: Jan Hubicka <jh@suse.cz> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent b520b85 commit a586df0

File tree

4 files changed

+35
-8
lines changed

4 files changed

+35
-8
lines changed

include/linux/compiler-gcc4.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,21 @@
2323
* code
2424
*/
2525
#define uninitialized_var(x) x = x
26+
27+
#if !(__GNUC__ == 4 && __GNUC_MINOR__ < 3)
28+
/* Mark functions as cold. gcc will assume any path leading to a call
29+
to them will be unlikely. This means a lot of manual unlikely()s
30+
are unnecessary now for any paths leading to the usual suspects
31+
like BUG(), printk(), panic() etc. [but let's keep them for now for
32+
older compilers]
33+
34+
Early snapshots of gcc 4.3 don't support this and we can't detect this
35+
in the preprocessor, but we can live with this because they're unreleased.
36+
Maketime probing would be overkill here.
37+
38+
gcc also has a __attribute__((__hot__)) to move hot functions into
39+
a special section, but I don't see any sense in this right now in
40+
the kernel context */
41+
#define __cold __attribute__((__cold__))
42+
43+
#endif

include/linux/compiler.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,13 @@ extern void __chk_io_ptr(const void __iomem *);
174174
# define __attribute_const__ /* unimplemented */
175175
#endif
176176

177+
/*
178+
* Tell gcc if a function is cold. The compiler will assume any path
179+
* directly leading to the call is unlikely.
180+
*/
181+
182+
#ifndef __cold
183+
#define __cold
184+
#endif
185+
177186
#endif /* __LINUX_COMPILER_H */

include/linux/init.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@
4040

4141
/* These are for everybody (although not all archs will actually
4242
discard it in modules) */
43-
#define __init __attribute__ ((__section__ (".init.text")))
43+
#define __init __attribute__ ((__section__ (".init.text"))) __cold
4444
#define __initdata __attribute__ ((__section__ (".init.data")))
4545
#define __exitdata __attribute__ ((__section__(".exit.data")))
46-
#define __exit_call __attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))
46+
#define __exit_call __attribute_used__ __attribute__ ((__section__ (".exitcall.exit"))) __cold
4747

4848
/* modpost check for section mismatches during the kernel build.
4949
* A section mismatch happens when there are references from a
@@ -59,9 +59,9 @@
5959
#define __initdata_refok __attribute__ ((__section__ (".data.init.refok")))
6060

6161
#ifdef MODULE
62-
#define __exit __attribute__ ((__section__(".exit.text")))
62+
#define __exit __attribute__ ((__section__(".exit.text"))) __cold
6363
#else
64-
#define __exit __attribute_used__ __attribute__ ((__section__(".exit.text")))
64+
#define __exit __attribute_used__ __attribute__ ((__section__(".exit.text"))) __cold
6565
#endif
6666

6767
/* For assembly routines */

include/linux/kernel.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ extern int cond_resched(void);
106106
extern struct atomic_notifier_head panic_notifier_list;
107107
extern long (*panic_blink)(long time);
108108
NORET_TYPE void panic(const char * fmt, ...)
109-
__attribute__ ((NORET_AND format (printf, 1, 2)));
109+
__attribute__ ((NORET_AND format (printf, 1, 2))) __cold;
110110
extern void oops_enter(void);
111111
extern void oops_exit(void);
112112
extern int oops_may_print(void);
@@ -155,14 +155,14 @@ extern void dump_thread(struct pt_regs *regs, struct user *dump);
155155
asmlinkage int vprintk(const char *fmt, va_list args)
156156
__attribute__ ((format (printf, 1, 0)));
157157
asmlinkage int printk(const char * fmt, ...)
158-
__attribute__ ((format (printf, 1, 2)));
158+
__attribute__ ((format (printf, 1, 2))) __cold;
159159
#else
160160
static inline int vprintk(const char *s, va_list args)
161161
__attribute__ ((format (printf, 1, 0)));
162162
static inline int vprintk(const char *s, va_list args) { return 0; }
163163
static inline int printk(const char *s, ...)
164164
__attribute__ ((format (printf, 1, 2)));
165-
static inline int printk(const char *s, ...) { return 0; }
165+
static inline int __cold printk(const char *s, ...) { return 0; }
166166
#endif
167167

168168
unsigned long int_sqrt(unsigned long);
@@ -212,7 +212,7 @@ extern enum system_states {
212212
#define TAINT_USER (1<<6)
213213
#define TAINT_DIE (1<<7)
214214

215-
extern void dump_stack(void);
215+
extern void dump_stack(void) __cold;
216216

217217
enum {
218218
DUMP_PREFIX_NONE,

0 commit comments

Comments
 (0)