> Hi! > > The inlining heuristics uses DECL_DECLARED_INLINE_P (whether a function > has been explicitly marked inline; that can be inline keyword, or for C++ > also constexpr keyword or defining a function inside of a class definition) > heavily to increase desirability of inlining a function etc. > In most cases it is desirable, people usually mark functions inline with > the intent that they are actually inlined.
Reading the discussion on the PR, one of argument for adding new attribute was that we should not make differnece between "constexr" and "constexpr inline" since C++ stnadard says it is the same. We already do such difference between class foo { int bar () { } inline int bar2 () { } }; Which is what DECL_DECLARED_INLINE was added for. so I am not sure if keeping this distinction is really that important. > > So far smoke tested on x86_64-linux, ok for trunk if it passes full > bootstrap/regtest? > > 2024-11-14 Jakub Jelinek <ja...@redhat.com> > > PR c++/93008 > gcc/ > * tree-core.h (struct tree_function_decl): Add feeble_inline_flag > bitfield. > * tree.h (DECL_FEEBLE_INLINE_P, DECL_OPTIMIZABLE_INLINE_P): Define. > * cgraphunit.cc (process_function_and_variable_attributes): Warn > on feeble_inline attribute on !DECL_DECLARED_INLINE_P function. > * symtab.cc (symtab_node::fixup_same_cpp_alias_visibility): Copy > over DECL_FEEBLE_INLINE_P as well. Formatting fixes. > * tree-inline.cc (tree_inlinable_function_p, expand_call_inline): Use > DECL_OPTIMIZABLE_INLINE_P instead of DECL_DECLARED_INLINE_P. > * ipa-cp.cc (devirtualization_time_bonus): Likewise. > * ipa-fnsummary.cc (ipa_call_context::estimate_size_and_time): > Likewise. > * ipa-icf.cc (sem_item::compare_referenced_symbol_properties): Punt > on DECL_FEEBLE_INLINE_P differences. > (sem_item::hash_referenced_symbol_properties): Hash also > DECL_FEEBLE_INLINE_P and DECL_IS_REPLACEABLE_OPERATOR. > * ipa-inline.cc (can_inline_edge_by_limits_p, > want_early_inline_function_p, want_inline_small_function_p, > want_inline_self_recursive_call_p, wrapper_heuristics_may_apply, > edge_badness, recursive_inlining, early_inline_small_functions): Use > DECL_OPTIMIZABLE_INLINE_P instead of DECL_DECLARED_INLINE_P. > * ipa-split.cc (consider_split, execute_split_functions): Likewise. > * lto-streamer-out.cc (hash_tree): Hash DECL_FEEBLE_INLINE_P and > DECL_IS_REPLACEABLE_OPERATOR. > * tree-streamer-in.cc (unpack_ts_function_decl_value_fields): Unpack > DECL_FEEBLE_INLINE_P. > * tree-streamer-out.cc (pack_ts_function_decl_value_fields): Pack > DECL_FEEBLE_INLINE_P. > * doc/invoke.texi (Winline): Document feeble_inline functions aren't > warned about. > * doc/extend.texi (feeble_inline function attribute): Document. > gcc/c-family/ > * c-attribs.cc (attr_always_inline_exclusions, > attr_noinline_exclusions): Add feeble_inline. > (attr_feeble_inline_exclusions): New variable. > (c_common_gnu_attributes): Add feeble_inline attribute. > (handle_feeble_inline_attribute): New function. > gcc/c/ > * c-decl.cc (merge_decls): Merge DECL_FEEBLE_INLINE_P. > gcc/cp/ > * decl.cc (duplicate_decls): Merge DECL_FEEBLE_INLINE_P. > * method.cc (implicitly_declare_fn): Copy DECL_FEEBLE_INLINE_P. > * optimize.cc (maybe_clone_body): Likewise. > gcc/testsuite/ > * c-c++-common/attr-feeble_inline-1.c: New test. > * gcc.dg/attr-feeble_inline-1.c: New test. > * g++.dg/ext/attr-feeble_inline-1.C: New test. > * g++.dg/ext/attr-feeble_inline-2.C: New test. > * g++.dg/ext/attr-feeble_inline-2.cc: New test. > > --- gcc/tree-core.h.jj 2024-11-14 12:25:50.257322008 +0100 > +++ gcc/tree-core.h 2024-11-14 13:12:50.711972132 +0100 > @@ -2054,8 +2054,9 @@ struct GTY(()) tree_function_decl { > unsigned has_debug_args_flag : 1; > unsigned versioned_function : 1; > unsigned replaceable_operator : 1; > + unsigned feeble_inline_flag : 1; > > - /* 11 bits left for future expansion. */ > + /* 10 bits left for future expansion. */ > /* 32 bits on 64-bit HW. */ > }; > > --- gcc/tree.h.jj 2024-11-14 12:25:50.434319603 +0100 > +++ gcc/tree.h 2024-11-14 13:14:32.541537830 +0100 > @@ -3480,6 +3480,20 @@ set_function_decl_type (tree decl, funct > #define DECL_NO_INLINE_WARNING_P(NODE) \ > (FUNCTION_DECL_CHECK (NODE)->function_decl.no_inline_warning_flag) > > +/* Nonzero in a FUNCTION_DECL means this function is has > + feeble_inline attribute, while it is DECL_DECLARED_INLINE_P, > + that declaration should be ignored for optimization purposes, > + it is declared inline only for other reasons (C++ constexpr > + so that it can be constant evaluated or get the C++ comdat behavior > + of inline functions. */ > +#define DECL_FEEBLE_INLINE_P(NODE) \ > + (FUNCTION_DECL_CHECK (NODE)->function_decl.feeble_inline_flag) > + > +/* Nonzero if inlining should prefer inlining this function. > + Shorthand for DECL_DECLARED_INLINE_P && !DECL_FEEBLE_INLINE_P. */ > +#define DECL_OPTIMIZABLE_INLINE_P(NODE) \ > + (DECL_DECLARED_INLINE_P (NODE) && !DECL_FEEBLE_INLINE_P (NODE)) We have 10 bits left, but it would also make sense to put the flag into inline summary and use explicit lookup_attribute elsewhere. Inliner is only place that cares about this in hot code. IPA parts of the patch looks OK however I wonder if simply clearing DECL_DECLARED_INLINE_P would have same effect? Honza