+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
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,
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,
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. */
return specs;
}
+
{
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;
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);
}
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;
#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
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)
{
{
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)
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
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
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
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;
}
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;
}
--- /dev/null
+/* 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" } } */