diff options
author | aldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-02-22 00:09:04 +0000 |
---|---|---|
committer | aldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-02-22 00:09:04 +0000 |
commit | af87ad830272721880f74898c75cc639a081fcec (patch) | |
tree | 81ecf94407355c68f26f5bc1ca604c5ff588e9da /gcc | |
parent | a4194ff76cc5b73c5f6513b9422ddc59ccd31535 (diff) | |
download | gcc-af87ad830272721880f74898c75cc639a081fcec.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@49947 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 31 | ||||
-rw-r--r-- | gcc/attribs.c | 30 | ||||
-rw-r--r-- | gcc/c-common.c | 7 | ||||
-rw-r--r-- | gcc/c-objc-common.c | 7 | ||||
-rw-r--r-- | gcc/config/rs6000/altivec.h | 32 | ||||
-rw-r--r-- | gcc/cp/decl.c | 1 | ||||
-rw-r--r-- | gcc/cp/tree.c | 4 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 20 | ||||
-rw-r--r-- | gcc/langhooks.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/attr-alwaysinline.c | 19 |
10 files changed, 151 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e4b437ceb2f..347c7f84615 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/attribs.c b/gcc/attribs.c index 7cb11724f83..543931add01 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -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; } + diff --git a/gcc/c-common.c b/gcc/c-common.c index dfdacca3c55..1e49104d563 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -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; diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c index 6554cf59de8..b2f996973ee 100644 --- a/gcc/c-objc-common.c +++ b/gcc/c-objc-common.c @@ -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; diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h index a25206d60f6..b18b60d456b 100644 --- a/gcc/config/rs6000/altivec.h +++ b/gcc/config/rs6000/altivec.h @@ -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 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index acac552ce4e..a91b3da3df1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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) { diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 2d99e029fe9..62f67e7e933 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 39e0fb9d260..68d0146bad8 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -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 diff --git a/gcc/langhooks.c b/gcc/langhooks.c index 4ad9ae3e960..c189a3b50b9 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -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; } diff --git a/gcc/testsuite/gcc.dg/attr-alwaysinline.c b/gcc/testsuite/gcc.dg/attr-alwaysinline.c new file mode 100644 index 00000000000..8ff92b23a72 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-alwaysinline.c @@ -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" } } */ |