From 24ad9cf0325bb5fedc9f0ca8bd70f78096d8d326 Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Thu, 19 Jun 2008 10:08:49 +0000 Subject: [PATCH] Fix up inlines for gcc 4.3 gcc 4.3 emits warnings for static inline functions that its heuristics decided not to inline. The workaround is to either mark appropriate functions as "hot" (a new attribute in gcc 4.3), or sometimes to use "extern inline" instead. With this fix I can validate with gcc 4.3 on Fedora 9. --- includes/SMP.h | 12 ++++++------ includes/SMPClosureOps.h | 25 +++++++++++-------------- includes/Stg.h | 28 +++++++++++++++++++++++++++- rts/Inlines.c | 5 +++++ rts/ProfHeap.c | 2 +- rts/sm/Evac.c | 6 +++--- rts/sm/Scav.c | 12 ++++++------ 7 files changed, 59 insertions(+), 31 deletions(-) create mode 100644 rts/Inlines.c diff --git a/includes/SMP.h b/includes/SMP.h index 0e6322d..eaac770 100644 --- a/includes/SMP.h +++ b/includes/SMP.h @@ -41,7 +41,7 @@ * Used for locking closures during updates (see lockClosure() below) * and the MVar primops. */ -INLINE_HEADER StgWord xchg(StgPtr p, StgWord w); +EXTERN_INLINE StgWord xchg(StgPtr p, StgWord w); /* * Compare-and-swap. Atomically does this: @@ -52,13 +52,13 @@ INLINE_HEADER StgWord xchg(StgPtr p, StgWord w); * return r; * } */ -INLINE_HEADER StgWord cas(StgVolatilePtr p, StgWord o, StgWord n); +EXTERN_INLINE StgWord cas(StgVolatilePtr p, StgWord o, StgWord n); /* * Prevents write operations from moving across this call in either * direction. */ -INLINE_HEADER void write_barrier(void); +EXTERN_INLINE void write_barrier(void); /* ---------------------------------------------------------------------------- Implementations @@ -67,7 +67,7 @@ INLINE_HEADER void write_barrier(void); * NB: the xchg instruction is implicitly locked, so we do not need * a lock prefix here. */ -INLINE_HEADER StgWord +EXTERN_INLINE StgWord xchg(StgPtr p, StgWord w) { StgWord result; @@ -106,7 +106,7 @@ xchg(StgPtr p, StgWord w) * CMPXCHG - the single-word atomic compare-and-exchange instruction. Used * in the STM implementation. */ -INLINE_HEADER StgWord +EXTERN_INLINE StgWord cas(StgVolatilePtr p, StgWord o, StgWord n) { #if i386_HOST_ARCH || x86_64_HOST_ARCH @@ -159,7 +159,7 @@ cas(StgVolatilePtr p, StgWord o, StgWord n) * control in C, and optionally a memory barrier instruction on CPUs * that require it (not x86 or x86_64). */ -INLINE_HEADER void +EXTERN_INLINE void write_barrier(void) { #if i386_HOST_ARCH || x86_64_HOST_ARCH __asm__ __volatile__ ("" : : : "memory"); diff --git a/includes/SMPClosureOps.h b/includes/SMPClosureOps.h index fe78168..a43222d 100644 --- a/includes/SMPClosureOps.h +++ b/includes/SMPClosureOps.h @@ -9,6 +9,9 @@ #ifndef SMPCLOSUREOPS_H #define SMPCLOSUREOPS_H +EXTERN_INLINE StgInfoTable *lockClosure(StgClosure *p); +EXTERN_INLINE void unlockClosure(StgClosure *p, const StgInfoTable *info); + #if defined(THREADED_RTS) /* ----------------------------------------------------------------------------- @@ -19,16 +22,9 @@ #define SPIN_COUNT 4000 -#ifdef KEEP_LOCKCLOSURE // We want a callable copy of lockClosure() so that we can refer to it // from .cmm files compiled using the native codegen. -extern StgInfoTable *lockClosure(StgClosure *p); -INLINE_ME -#else -INLINE_HEADER -#endif -StgInfoTable * -lockClosure(StgClosure *p) +EXTERN_INLINE StgInfoTable *lockClosure(StgClosure *p) { StgWord info; do { @@ -41,8 +37,7 @@ lockClosure(StgClosure *p) } while (1); } -INLINE_HEADER void -unlockClosure(StgClosure *p, const StgInfoTable *info) +EXTERN_INLINE void unlockClosure(StgClosure *p, const StgInfoTable *info) { // This is a strictly ordered write, so we need a write_barrier(): write_barrier(); @@ -51,21 +46,23 @@ unlockClosure(StgClosure *p, const StgInfoTable *info) #else /* !THREADED_RTS */ -INLINE_HEADER StgInfoTable * +EXTERN_INLINE StgInfoTable * lockClosure(StgClosure *p) { return (StgInfoTable *)p->header.info; } -INLINE_HEADER void +EXTERN_INLINE void unlockClosure(StgClosure *p STG_UNUSED, const StgInfoTable *info STG_UNUSED) { /* nothing */ } #endif /* THREADED_RTS */ // Handy specialised versions of lockClosure()/unlockClosure() -INLINE_HEADER void lockTSO(StgTSO *tso) +EXTERN_INLINE void lockTSO(StgTSO *tso); +EXTERN_INLINE void lockTSO(StgTSO *tso) { lockClosure((StgClosure *)tso); } -INLINE_HEADER void unlockTSO(StgTSO *tso) +EXTERN_INLINE void unlockTSO(StgTSO *tso); +EXTERN_INLINE void unlockTSO(StgTSO *tso) { unlockClosure((StgClosure*)tso, (const StgInfoTable *)&stg_TSO_info); } #endif /* SMPCLOSUREOPS_H */ diff --git a/includes/Stg.h b/includes/Stg.h index 35f4eda..022b385 100644 --- a/includes/Stg.h +++ b/includes/Stg.h @@ -75,21 +75,41 @@ /* * 'Portable' inlining: - * INLINE_HEADER is for inline functions in header files + * INLINE_HEADER is for inline functions in header files (macros) * STATIC_INLINE is for inline functions in source files + * EXTERN_INLINE is for functions that we want to inline sometimes */ #if defined(__GNUC__) || defined( __INTEL_COMPILER) + # define INLINE_HEADER static inline # define INLINE_ME inline # define STATIC_INLINE INLINE_HEADER + +# if defined(KEEP_INLINES) +# define EXTERN_INLINE inline +# else +# define EXTERN_INLINE extern inline +# endif + #elif defined(_MSC_VER) + # define INLINE_HEADER __inline static # define INLINE_ME __inline # define STATIC_INLINE INLINE_HEADER + +# if defined(KEEP_INLINES) +# define EXTERN_INLINE __inline +# else +# define EXTERN_INLINE __inline extern +# endif + #else + # error "Don't know how to inline functions with your C compiler." + #endif + /* * GCC attributes */ @@ -105,6 +125,12 @@ #define GNUC3_ATTRIBUTE(at) #endif +#if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3 +#define GNUC_ATTR_HOT __attribute__((hot)) +#else +#define GNUC_ATTR_HOT /* nothing */ +#endif + #define STG_UNUSED GNUC3_ATTRIBUTE(__unused__) /* ----------------------------------------------------------------------------- diff --git a/rts/Inlines.c b/rts/Inlines.c new file mode 100644 index 0000000..5d2be70 --- /dev/null +++ b/rts/Inlines.c @@ -0,0 +1,5 @@ +// all functions declared with EXTERN_INLINE in the header files get +// compiled for real here, just in case the definition was not inlined +// at some call site: +#define KEEP_INLINES +#include "Rts.h" diff --git a/rts/ProfHeap.c b/rts/ProfHeap.c index 599b479..9aca5a9 100644 --- a/rts/ProfHeap.c +++ b/rts/ProfHeap.c @@ -182,7 +182,7 @@ static char *type_names[] = { * the band to which this closure's heap space is attributed in the * heap profile. * ------------------------------------------------------------------------- */ -STATIC_INLINE void * +static void * closureIdentity( StgClosure *p ) { switch (RtsFlags.ProfFlags.doHeapProfile) { diff --git a/rts/sm/Evac.c b/rts/sm/Evac.c index 3b68c62..375cf81 100644 --- a/rts/sm/Evac.c +++ b/rts/sm/Evac.c @@ -86,7 +86,7 @@ alloc_for_copy (nat size, step *stp) The evacuate() code -------------------------------------------------------------------------- */ -STATIC_INLINE void +STATIC_INLINE GNUC_ATTR_HOT void copy_tag(StgClosure **p, const StgInfoTable *info, StgClosure *src, nat size, step *stp, StgWord tag) { @@ -218,7 +218,7 @@ spin: /* Copy wrappers that don't tag the closure after copying */ -STATIC_INLINE void +STATIC_INLINE GNUC_ATTR_HOT void copy(StgClosure **p, const StgInfoTable *info, StgClosure *src, nat size, step *stp) { @@ -267,7 +267,7 @@ copy(StgClosure **p, const StgInfoTable *info, extra reads/writes than we save. ------------------------------------------------------------------------- */ -REGPARM1 void +REGPARM1 GNUC_ATTR_HOT void evacuate(StgClosure **p) { bdescr *bd = NULL; diff --git a/rts/sm/Scav.c b/rts/sm/Scav.c index f61d6b7..ab55e8a 100644 --- a/rts/sm/Scav.c +++ b/rts/sm/Scav.c @@ -140,7 +140,7 @@ scavenge_arg_block (StgFunInfoTable *fun_info, StgClosure **args) return p; } -STATIC_INLINE StgPtr +STATIC_INLINE GNUC_ATTR_HOT StgPtr scavenge_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size) { StgPtr p; @@ -179,7 +179,7 @@ scavenge_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size) return p; } -STATIC_INLINE StgPtr +STATIC_INLINE GNUC_ATTR_HOT StgPtr scavenge_PAP (StgPAP *pap) { evacuate(&pap->fun); @@ -230,7 +230,7 @@ scavenge_large_srt_bitmap( StgLargeSRT *large_srt ) * srt field in the info table. That's ok, because we'll * never dereference it. */ -STATIC_INLINE void +STATIC_INLINE GNUC_ATTR_HOT void scavenge_srt (StgClosure **srt, nat srt_bitmap) { nat bitmap; @@ -270,7 +270,7 @@ scavenge_srt (StgClosure **srt, nat srt_bitmap) } -STATIC_INLINE void +STATIC_INLINE GNUC_ATTR_HOT void scavenge_thunk_srt(const StgInfoTable *info) { StgThunkInfoTable *thunk_info; @@ -281,7 +281,7 @@ scavenge_thunk_srt(const StgInfoTable *info) scavenge_srt((StgClosure **)GET_SRT(thunk_info), thunk_info->i.srt_bitmap); } -STATIC_INLINE void +STATIC_INLINE GNUC_ATTR_HOT void scavenge_fun_srt(const StgInfoTable *info) { StgFunInfoTable *fun_info; @@ -304,7 +304,7 @@ scavenge_fun_srt(const StgInfoTable *info) idea. -------------------------------------------------------------------------- */ -static void +static GNUC_ATTR_HOT void scavenge_block (bdescr *bd) { StgPtr p, q; -- 1.7.10.4