summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authoraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>2002-02-22 00:09:04 +0000
committeraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>2002-02-22 00:09:04 +0000
commitaf87ad830272721880f74898c75cc639a081fcec (patch)
tree81ecf94407355c68f26f5bc1ca604c5ff588e9da /gcc
parenta4194ff76cc5b73c5f6513b9422ddc59ccd31535 (diff)
downloadgcc-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/ChangeLog31
-rw-r--r--gcc/attribs.c30
-rw-r--r--gcc/c-common.c7
-rw-r--r--gcc/c-objc-common.c7
-rw-r--r--gcc/config/rs6000/altivec.h32
-rw-r--r--gcc/cp/decl.c1
-rw-r--r--gcc/cp/tree.c4
-rw-r--r--gcc/doc/extend.texi20
-rw-r--r--gcc/langhooks.c11
-rw-r--r--gcc/testsuite/gcc.dg/attr-alwaysinline.c19
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" } } */