]> gcc.gnu.org Git - gcc.git/commitdiff
attr-alwaysinline.c: New.
authorAldy Hernandez <aldyh@redhat.com>
Fri, 22 Feb 2002 00:09:04 +0000 (00:09 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Fri, 22 Feb 2002 00:09:04 +0000 (00:09 +0000)
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

gcc/ChangeLog
gcc/attribs.c
gcc/c-common.c
gcc/c-objc-common.c
gcc/config/rs6000/altivec.h
gcc/cp/decl.c
gcc/cp/tree.c
gcc/doc/extend.texi
gcc/langhooks.c
gcc/testsuite/gcc.dg/attr-alwaysinline.c [new file with mode: 0644]

index e4b437ceb2f5f7b44bcb18b0f93803846b9c0a3f..347c7f8461503bd8f48622cb8646abfd840b5611 100644 (file)
@@ -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
index 7cb11724f8326275e25facae75c62b1e189a6add..543931add01195122310a9c8137f7e7144360fc4 100644 (file)
@@ -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;
 }
+
index dfdacca3c55ecf6af202a251d297ea134aff4653..1e49104d5631154078a7d4fd9f3eadfe7fba0e6d 100644 (file)
@@ -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;
index 6554cf59de8c24bf30aa4621f86dd2ebf286d8bd..b2f996973eebf4dab27685df54ccf60a5c8c5786 100644 (file)
@@ -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;
index a25206d60f61e90defd6ebc8a63906ff5324e8a2..b18b60d456b914b0d8de965bff69de8fcfd3a1b2 100644 (file)
@@ -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
index acac552ce4e6ada4afa6a3e887cebb2434449a3f..a91b3da3df1fb0116efbf59d8285804616502515 100644 (file)
@@ -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)
     {
index 2d99e029fe9261412bb6109c1a8d2354b228803d..62f67e7e9336965838752fe75b118fb4d5d70a0a 100644 (file)
@@ -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)
index 39e0fb9d2607673eb2daf16058f8dde7ea9f2b50..68d0146bad8fd66361e79afd5a7779a0c2a9acff 100644 (file)
@@ -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
index 4ad9ae3e9604d47e6dcd55894c2245ecb6f44089..c189a3b50b90ce4caa4b25cacf4cfbbbba424e71 100644 (file)
@@ -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 (file)
index 0000000..8ff92b2
--- /dev/null
@@ -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" } } */
This page took 0.095379 seconds and 5 git commands to generate.