mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-07 14:57:21 +08:00
attr-alwaysinline.c: New.
2002-02-21 Aldy Hernandez <aldyh@redhat.com> * gcc.dg/attr-alwaysinline.c: New. * c-common.c (c_common_post_options): Set inline trees by default. * doc/extend.texi (Function Attributes): Document always_inline attribute. Update documentation about inlining when not optimizing. * cp/decl.c (duplicate_decls): Merge always_inline attribute. * cp/tree.c (cp_cannot_inline_tree_fn): Do not inline at -O0 unless DECL_ALWAYS_INLINE. * c-objc-common.c (c_cannot_inline_tree_fn): Do not inline at -O0 unless DECL_ALWAYS_INLINE. (c_disregard_inline_limits): Disregard if always_inline set. * langhooks.c (lhd_tree_inlining_disregard_inline_limits): Disregard if always_inline set. (lhd_tree_inlining_cannot_inline_tree_fn): Do not inline at -O0 unless DECL_ALWAYS_INLINE. * attribs.c (handle_always_inline_attribute): New. (c_common_attribute_table): Add always_inline. * config/rs6000/altivec.h: Add prototypes for builtins requiring the always_inline attribute. From-SVN: r49947
This commit is contained in:
parent
c410d49e43
commit
6aa77e6c39
@ -1,3 +1,34 @@
|
||||
2002-02-21 Aldy Hernandez <aldyh@redhat.com>
|
||||
|
||||
* testsuite/gcc.dg/attr-alwaysinline.c: New.
|
||||
|
||||
* c-common.c (c_common_post_options): Set inline trees by
|
||||
default.
|
||||
|
||||
* doc/extend.texi (Function Attributes): Document always_inline
|
||||
attribute.
|
||||
Update documentation about inlining when not optimizing.
|
||||
|
||||
* cp/decl.c (duplicate_decls): Merge always_inline attribute.
|
||||
|
||||
* cp/tree.c (cp_cannot_inline_tree_fn): Do not inline at -O0
|
||||
unless DECL_ALWAYS_INLINE.
|
||||
|
||||
* c-objc-common.c (c_cannot_inline_tree_fn): Do not inline at -O0
|
||||
unless DECL_ALWAYS_INLINE.
|
||||
(c_disregard_inline_limits): Disregard if always_inline set.
|
||||
|
||||
* langhooks.c (lhd_tree_inlining_disregard_inline_limits):
|
||||
Disregard if always_inline set.
|
||||
(lhd_tree_inlining_cannot_inline_tree_fn): Do not inline at -O0
|
||||
unless DECL_ALWAYS_INLINE.
|
||||
|
||||
* attribs.c (handle_always_inline_attribute): New.
|
||||
(c_common_attribute_table): Add always_inline.
|
||||
|
||||
* config/rs6000/altivec.h: Add prototypes for builtins
|
||||
requiring the always_inline attribute.
|
||||
|
||||
2002-02-21 Eric Christopher <echristo@redhat.com>
|
||||
|
||||
* expmed.c (store_bit_field): Try to simplify the subreg
|
||||
|
@ -51,6 +51,8 @@ static tree handle_noreturn_attribute PARAMS ((tree *, tree, tree, int,
|
||||
bool *));
|
||||
static tree handle_noinline_attribute PARAMS ((tree *, tree, tree, int,
|
||||
bool *));
|
||||
static tree handle_always_inline_attribute PARAMS ((tree *, tree, tree, int,
|
||||
bool *));
|
||||
static tree handle_used_attribute PARAMS ((tree *, tree, tree, int,
|
||||
bool *));
|
||||
static tree handle_unused_attribute PARAMS ((tree *, tree, tree, int,
|
||||
@ -109,6 +111,8 @@ static const struct attribute_spec c_common_attribute_table[] =
|
||||
handle_noreturn_attribute },
|
||||
{ "noinline", 0, 0, true, false, false,
|
||||
handle_noinline_attribute },
|
||||
{ "always_inline", 0, 0, true, false, false,
|
||||
handle_always_inline_attribute },
|
||||
{ "used", 0, 0, true, false, false,
|
||||
handle_used_attribute },
|
||||
{ "unused", 0, 0, false, false, false,
|
||||
@ -563,6 +567,31 @@ handle_noinline_attribute (node, name, args, flags, no_add_attrs)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle a "always_inline" attribute; arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
static tree
|
||||
handle_always_inline_attribute (node, name, args, flags, no_add_attrs)
|
||||
tree *node;
|
||||
tree name;
|
||||
tree args ATTRIBUTE_UNUSED;
|
||||
int flags ATTRIBUTE_UNUSED;
|
||||
bool *no_add_attrs;
|
||||
{
|
||||
if (TREE_CODE (*node) == FUNCTION_DECL)
|
||||
{
|
||||
/* Do nothing else, just set the attribute. We'll get at
|
||||
it later with lookup_attribute. */
|
||||
}
|
||||
else
|
||||
{
|
||||
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle a "used" attribute; arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
@ -1431,3 +1460,4 @@ strip_attrs (specs_attrs)
|
||||
|
||||
return specs;
|
||||
}
|
||||
|
||||
|
@ -4109,15 +4109,14 @@ c_common_post_options ()
|
||||
{
|
||||
cpp_post_options (parse_in);
|
||||
|
||||
flag_inline_trees = 1;
|
||||
|
||||
/* Use tree inlining if possible. Function instrumentation is only
|
||||
done in the RTL level, so we disable tree inlining. */
|
||||
if (! flag_instrument_function_entry_exit)
|
||||
{
|
||||
if (!flag_no_inline)
|
||||
{
|
||||
flag_inline_trees = 1;
|
||||
flag_no_inline = 1;
|
||||
}
|
||||
flag_no_inline = 1;
|
||||
if (flag_inline_functions)
|
||||
{
|
||||
flag_inline_trees = 2;
|
||||
|
@ -59,6 +59,9 @@ int
|
||||
c_disregard_inline_limits (fn)
|
||||
tree fn;
|
||||
{
|
||||
if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) != NULL)
|
||||
return 1;
|
||||
|
||||
return DECL_DECLARED_INLINE_P (fn) && DECL_EXTERNAL (fn);
|
||||
}
|
||||
|
||||
@ -142,6 +145,10 @@ c_cannot_inline_tree_fn (fnp)
|
||||
tree fn = *fnp;
|
||||
tree t;
|
||||
|
||||
if (optimize == 0
|
||||
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
|
||||
return 1;
|
||||
|
||||
if (! function_attribute_inlinable_p (fn))
|
||||
{
|
||||
DECL_UNINLINABLE (fn) = 1;
|
||||
|
@ -70,6 +70,38 @@ extern int __altivec_link_error_invalid_argument ();
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/* Prototypes for builtins that take literals and must always be
|
||||
inlined. */
|
||||
inline vector float vec_ctf (vector unsigned int, const char) __attribute__ ((always_inline));
|
||||
inline vector float vec_ctf (vector signed int, const char) __attribute__ ((always_inline));
|
||||
inline vector signed int vec_cts (vector float, const char) __attribute__ ((always_inline));
|
||||
inline vector unsigned int vec_ctu (vector float, const char) __attribute__ ((always_inline));
|
||||
inline void vec_dss (const char) __attribute__ ((always_inline));
|
||||
inline void vec_dst (void *, int, const char) __attribute__ ((always_inline));
|
||||
inline void vec_dstst (void *, int, const char) __attribute__ ((always_inline));
|
||||
inline void vec_dststt (void *, int, const char) __attribute__ ((always_inline));
|
||||
inline void vec_dstt (void *, int, const char) __attribute__ ((always_inline));
|
||||
inline vector float vec_sld (vector float, vector float, const char) __attribute__ ((always_inline));
|
||||
inline vector signed int vec_sld (vector signed int, vector signed int, const char) __attribute__ ((always_inline));
|
||||
inline vector unsigned int vec_sld (vector unsigned int, vector unsigned int, const char) __attribute__ ((always_inline));
|
||||
inline vector signed short vec_sld (vector signed short, vector signed short, const char) __attribute__ ((always_inline));
|
||||
inline vector unsigned short vec_sld (vector unsigned short, vector unsigned short, const char) __attribute__ ((always_inline));
|
||||
inline vector signed char vec_sld (vector signed char, vector signed char, const char) __attribute__ ((always_inline));
|
||||
inline vector unsigned char vec_sld (vector unsigned char, vector unsigned char, const char) __attribute__ ((always_inline));
|
||||
inline vector signed char vec_splat (vector signed char, const char) __attribute__ ((always_inline));
|
||||
inline vector unsigned char vec_splat (vector unsigned char, const char) __attribute__ ((always_inline));
|
||||
inline vector signed short vec_splat (vector signed short, const char) __attribute__ ((always_inline));
|
||||
inline vector unsigned short vec_splat (vector unsigned short, const char) __attribute__ ((always_inline));
|
||||
inline vector float vec_splat (vector float, const char) __attribute__ ((always_inline));
|
||||
inline vector signed int vec_splat (vector signed int, const char) __attribute__ ((always_inline));
|
||||
inline vector unsigned int vec_splat (vector unsigned int, const char) __attribute__ ((always_inline));
|
||||
inline vector signed char vec_splat_s8 (const char) __attribute__ ((always_inline));
|
||||
inline vector signed short vec_splat_s16 (const char) __attribute__ ((always_inline));
|
||||
inline vector signed int vec_splat_s32 (const char) __attribute__ ((always_inline));
|
||||
inline vector unsigned char vec_splat_u8 (const char) __attribute__ ((always_inline));
|
||||
inline vector unsigned short vec_splat_u16 (const char) __attribute__ ((always_inline));
|
||||
inline vector unsigned int vec_splat_u32 (const char) __attribute__ ((always_inline));
|
||||
|
||||
/* vec_abs */
|
||||
|
||||
inline vector signed char
|
||||
|
@ -3482,6 +3482,7 @@ duplicate_decls (newdecl, olddecl)
|
||||
except for any that we copy here from the old type. */
|
||||
DECL_ATTRIBUTES (newdecl)
|
||||
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
|
||||
decl_attributes (&newdecl, DECL_ATTRIBUTES (newdecl), 0);
|
||||
|
||||
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
|
||||
{
|
||||
|
@ -2099,6 +2099,10 @@ cp_cannot_inline_tree_fn (fnp)
|
||||
{
|
||||
tree fn = *fnp;
|
||||
|
||||
if (optimize == 0
|
||||
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
|
||||
return 1;
|
||||
|
||||
/* We can inline a template instantiation only if it's fully
|
||||
instantiated. */
|
||||
if (DECL_TEMPLATE_INFO (fn)
|
||||
|
@ -1880,7 +1880,8 @@ The keyword @code{__attribute__} allows you to specify special
|
||||
attributes when making a declaration. This keyword is followed by an
|
||||
attribute specification inside double parentheses. The following
|
||||
attributes are currently defined for functions on all targets:
|
||||
@code{noreturn}, @code{noinline}, @code{pure}, @code{const},
|
||||
@code{noreturn}, @code{noinline}, @code{always_inline},
|
||||
@code{pure}, @code{const},
|
||||
@code{format}, @code{format_arg}, @code{no_instrument_function},
|
||||
@code{section}, @code{constructor}, @code{destructor}, @code{used},
|
||||
@code{unused}, @code{deprecated}, @code{weak}, @code{malloc}, and
|
||||
@ -1946,6 +1947,12 @@ volatile voidfn fatal;
|
||||
This function attribute prevents a function from being considered for
|
||||
inlining.
|
||||
|
||||
@cindex @code{always_inline} function attribute
|
||||
@item always_inline
|
||||
Generally, functions are not inlined unless optimization is specified.
|
||||
For functions declared inline, this attribute inlines the function even
|
||||
if no optimization level was specified.
|
||||
|
||||
@cindex @code{pure} function attribute
|
||||
@item pure
|
||||
Many functions have no effects except the return value and their
|
||||
@ -3388,10 +3395,13 @@ existing semantics will remain available when @option{-std=gnu89} is
|
||||
specified, but eventually the default will be @option{-std=gnu99} and
|
||||
that will implement the C99 semantics, though it does not do so yet.)
|
||||
|
||||
GCC does not inline any functions when not optimizing. It is not
|
||||
clear whether it is better to inline or not, in this case, but we found
|
||||
that a correct implementation when not optimizing was difficult. So we
|
||||
did the easy thing, and turned it off.
|
||||
GCC does not inline any functions when not optimizing unless you specify
|
||||
the @samp{always_inline} attribute for the function, like this:
|
||||
|
||||
@example
|
||||
/* Prototype. */
|
||||
inline void foo (const char) __attribute__((always_inline));
|
||||
@end example
|
||||
|
||||
@node Extended Asm
|
||||
@section Assembler Instructions with C Expression Operands
|
||||
|
@ -153,8 +153,12 @@ lhd_tree_inlining_walk_subtrees (tp,subtrees,func,data,htab)
|
||||
|
||||
int
|
||||
lhd_tree_inlining_cannot_inline_tree_fn (fnp)
|
||||
tree *fnp ATTRIBUTE_UNUSED;
|
||||
tree *fnp;
|
||||
{
|
||||
if (optimize == 0
|
||||
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (*fnp)) == NULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -164,8 +168,11 @@ lhd_tree_inlining_cannot_inline_tree_fn (fnp)
|
||||
|
||||
int
|
||||
lhd_tree_inlining_disregard_inline_limits (fn)
|
||||
tree fn ATTRIBUTE_UNUSED;
|
||||
tree fn;
|
||||
{
|
||||
if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) != NULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
19
gcc/testsuite/gcc.dg/attr-alwaysinline.c
Normal file
19
gcc/testsuite/gcc.dg/attr-alwaysinline.c
Normal file
@ -0,0 +1,19 @@
|
||||
/* Test always_inline attribute, which forces inlining of functions
|
||||
even at no optimization. */
|
||||
/* Origin: Aldy Hernandez <aldyh@redhat.com>. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0" } */
|
||||
|
||||
static inline int sabrina (void) __attribute__((always_inline));
|
||||
|
||||
static inline int sabrina (void)
|
||||
{
|
||||
return 13;
|
||||
}
|
||||
|
||||
int bar (void)
|
||||
{
|
||||
return sabrina () + 68;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-not "sabrina" } } */
|
Loading…
Reference in New Issue
Block a user