Hi! So here is a proof of concept of an attribute that disables inlining, cloning, ICF, IPA VRP, IPA bit CCP, IPA RA, pure/const/throw discovery. Does it look reasonable? Anything still missing? No testsuite coverage yet, I bet we'd want to check for all those opts and see that they aren't happening if the attribute is present.
2016-12-15 Jakub Jelinek <ja...@redhat.com> * attribs.c (decl_attributes): Imply noinline, noclone, no_icf and used attributes for noipa attribute. For naked attribute use lookup_attribute first before lookup_attribute_spec. * final.c (rest_of_handle_final): Disable IPA RA for functions with noipa attribute. * cgraph.c (cgraph_node::get_availability): Return AVAIL_INTERPOSABLE for functions with noipa attribute. * doc/extend.texi: Document noipa function attribute. c-family/ * c-attribs.c (c_common_attribute_table): Add noipa attribute. (handle_noipa_attribute): New function. --- gcc/attribs.c.jj 2016-10-31 13:28:05.000000000 +0100 +++ gcc/attribs.c 2016-12-15 10:50:54.809973594 +0100 @@ -404,8 +404,8 @@ decl_attributes (tree *node, tree attrib those targets that support it. */ if (TREE_CODE (*node) == FUNCTION_DECL && attributes - && lookup_attribute_spec (get_identifier ("naked")) - && lookup_attribute ("naked", attributes) != NULL) + && lookup_attribute ("naked", attributes) != NULL + && lookup_attribute_spec (get_identifier ("naked"))) { if (lookup_attribute ("noinline", attributes) == NULL) attributes = tree_cons (get_identifier ("noinline"), NULL, attributes); @@ -414,6 +414,26 @@ decl_attributes (tree *node, tree attrib attributes = tree_cons (get_identifier ("noclone"), NULL, attributes); } + /* A "noipa" function attribute implies "noinline", "noclone", "no_icf" and + "used" for those targets that support it. */ + if (TREE_CODE (*node) == FUNCTION_DECL + && attributes + && lookup_attribute ("noipa", attributes) != NULL + && lookup_attribute_spec (get_identifier ("noipa"))) + { + if (lookup_attribute ("noinline", attributes) == NULL) + attributes = tree_cons (get_identifier ("noinline"), NULL, attributes); + + if (lookup_attribute ("noclone", attributes) == NULL) + attributes = tree_cons (get_identifier ("noclone"), NULL, attributes); + + if (lookup_attribute ("no_icf", attributes) == NULL) + attributes = tree_cons (get_identifier ("no_icf"), NULL, attributes); + + if (lookup_attribute ("used", attributes) == NULL) + attributes = tree_cons (get_identifier ("used"), NULL, attributes); + } + targetm.insert_attributes (*node, &attributes); for (a = attributes; a; a = TREE_CHAIN (a)) --- gcc/final.c.jj 2016-11-25 09:49:47.000000000 +0100 +++ gcc/final.c 2016-12-15 11:38:10.660080949 +0100 @@ -4473,7 +4473,8 @@ rest_of_handle_final (void) assemble_start_function (current_function_decl, fnname); final_start_function (get_insns (), asm_out_file, optimize); final (get_insns (), asm_out_file, optimize); - if (flag_ipa_ra) + if (flag_ipa_ra + && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl))) collect_fn_hard_reg_usage (); final_end_function (); --- gcc/cgraph.c.jj 2016-12-07 20:10:16.000000000 +0100 +++ gcc/cgraph.c 2016-12-15 12:20:11.449481168 +0100 @@ -2255,7 +2255,8 @@ cgraph_node::get_availability (symtab_no avail = AVAIL_AVAILABLE; else if (transparent_alias) ultimate_alias_target (&avail, ref); - else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl))) + else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)) + || lookup_attribute ("noipa", DECL_ATTRIBUTES (decl))) avail = AVAIL_INTERPOSABLE; else if (!externally_visible) avail = AVAIL_AVAILABLE; --- gcc/doc/extend.texi.jj 2016-12-15 11:26:07.000000000 +0100 +++ gcc/doc/extend.texi 2016-12-15 12:19:32.738996533 +0100 @@ -2955,6 +2955,15 @@ asm (""); (@pxref{Extended Asm}) in the called function, to serve as a special side-effect. +@item noipa +@cindex @code{noipa} function attribute +Disable interprocedural optimizations between the function with this +attribute and its callers, as if the body of the function is not available +when optimizing callers and the callers are unavailable when optimizing +the body. This attribute implies @code{noinline}, @code{noclone}, +@code{no_icf} and @code{used} attributes and in the future might +imply further newly added attributes. + @item nonnull (@var{arg-index}, @dots{}) @cindex @code{nonnull} function attribute @cindex functions with non-null pointer arguments --- gcc/c-family/c-attribs.c.jj 2016-12-02 09:37:19.000000000 +0100 +++ gcc/c-family/c-attribs.c 2016-12-15 10:48:43.743724788 +0100 @@ -63,6 +63,7 @@ static tree handle_stack_protect_attribu static tree handle_noinline_attribute (tree *, tree, tree, int, bool *); static tree handle_noclone_attribute (tree *, tree, tree, int, bool *); static tree handle_noicf_attribute (tree *, tree, tree, int, bool *); +static tree handle_noipa_attribute (tree *, tree, tree, int, bool *); static tree handle_leaf_attribute (tree *, tree, tree, int, bool *); static tree handle_always_inline_attribute (tree *, tree, tree, int, bool *); @@ -173,6 +174,8 @@ const struct attribute_spec c_common_att handle_noclone_attribute, false }, { "no_icf", 0, 0, true, false, false, handle_noicf_attribute, false }, + { "noipa", 0, 0, true, false, false, + handle_noipa_attribute, false }, { "leaf", 0, 0, true, false, false, handle_leaf_attribute, false }, { "always_inline", 0, 0, true, false, false, @@ -680,6 +683,22 @@ handle_noicf_attribute (tree *node, tree { if (TREE_CODE (*node) != FUNCTION_DECL) { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "noipa" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_noipa_attribute (tree *node, tree name, tree args, + int flags, bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { warning (OPT_Wattributes, "%qE attribute ignored", name); *no_add_attrs = true; } Jakub