From 036ea39917b0ef6f07a7c3c3c06002c73fd238f5 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 27 Jul 2017 09:53:33 +0200 Subject: [PATCH] attribs.c (decl_attributes): Imply noinline, noclone and no_icf attributes for noipa attribute. * attribs.c (decl_attributes): Imply noinline, noclone and no_icf 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. * ipa-visibility.c (non_local_p): Fix comment typos. Return true for functions with noipa attribute. (cgraph_externally_visible_p): Return true 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. * tree-ssa-structalias.c (refered_from_nonlocal_fn): Set *nonlocal_p also for functions with noipa attribute. (ipa_pta_execute): Set nonlocal_p also for nodes with noipa attribute. c-family/ * c-attribs.c (c_common_attribute_table): Add noipa attribute. (handle_noipa_attribute): New function. testsuite/ * gcc.dg/attr-noipa.c: New test. * gcc.dg/ipa/ipa-pta-18.c: New test. * gcc.dg/ipa/ipa-sra-11.c: New test. From-SVN: r250607 --- gcc/ChangeLog | 18 +++ gcc/attribs.c | 21 ++- gcc/c-family/ChangeLog | 5 + gcc/c-family/c-attribs.c | 18 +++ gcc/cgraph.c | 3 +- gcc/doc/extend.texi | 13 ++ gcc/final.c | 3 +- gcc/ipa-visibility.c | 5 +- gcc/testsuite/ChangeLog | 6 + gcc/testsuite/gcc.dg/attr-noipa.c | 188 ++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/ipa/ipa-pta-18.c | 26 ++++ gcc/testsuite/gcc.dg/ipa/ipa-sra-11.c | 39 ++++++ gcc/tree-ssa-structalias.c | 7 +- 13 files changed, 345 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/attr-noipa.c create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-pta-18.c create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-sra-11.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6866087dbea..89180b7d9c2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2017-07-27 Jakub Jelinek + + * attribs.c (decl_attributes): Imply noinline, noclone and no_icf + 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. + * ipa-visibility.c (non_local_p): Fix comment typos. Return true + for functions with noipa attribute. + (cgraph_externally_visible_p): Return true 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. + * tree-ssa-structalias.c (refered_from_nonlocal_fn): Set *nonlocal_p + also for functions with noipa attribute. + (ipa_pta_execute): Set nonlocal_p also for nodes with noipa attribute. + 2017-07-26 Andrew Pinski * config/aarch64/aarch64.c (thunderx_vector_cost): Decrease cost of diff --git a/gcc/attribs.c b/gcc/attribs.c index 5eb19e82795..05fa8ef8692 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -404,8 +404,8 @@ decl_attributes (tree *node, tree attributes, int flags) 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,23 @@ decl_attributes (tree *node, tree attributes, int flags) attributes = tree_cons (get_identifier ("noclone"), NULL, attributes); } + /* A "noipa" function attribute implies "noinline", "noclone" and "no_icf" + 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); + } + targetm.insert_attributes (*node, &attributes); for (a = attributes; a; a = TREE_CHAIN (a)) diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index a457a6c78e4..4a2b9ad430f 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2017-07-27 Jakub Jelinek + + * c-attribs.c (c_common_attribute_table): Add noipa attribute. + (handle_noipa_attribute): New function. + 2017-07-07 Torsten Duwe * c-attribs.c (c_common_attribute_table): Add entry for diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index ecb00c1d5b9..0d9ab2d6ae0 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -66,6 +66,7 @@ static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *); 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 *); @@ -178,6 +179,8 @@ const struct attribute_spec c_common_attribute_table[] = 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, @@ -698,6 +701,21 @@ handle_asan_odr_indicator_attribute (tree *, tree, tree, int, bool *) static tree handle_stack_protect_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) +{ + 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, int, bool *no_add_attrs) { if (TREE_CODE (*node) != FUNCTION_DECL) { diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 2f820f1bb67..d7c9ba61795 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2319,7 +2319,8 @@ cgraph_node::get_availability (symtab_node *ref) 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; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 156f7f2569c..6934b4cde3e 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2984,6 +2984,19 @@ 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} and +@code{no_icf} attributes. However, this attribute is not equivalent +to a combination of other attributes, because its purpose is to suppress +existing and future optimizations employing interprocedural analysis, +including those that do not have an attribute suitable for disabling +them individually. This attribute is supported mainly for the purpose +of testing the compiler. + @item nonnull (@var{arg-index}, @dots{}) @cindex @code{nonnull} function attribute @cindex functions with non-null pointer arguments diff --git a/gcc/final.c b/gcc/final.c index 356c923c4cd..2a24f4fe102 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -4492,7 +4492,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 (); diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c index 13cf2a3a1cf..3033f20e3f1 100644 --- a/gcc/ipa-visibility.c +++ b/gcc/ipa-visibility.c @@ -92,10 +92,11 @@ non_local_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) { return !(node->only_called_directly_or_aliased_p () /* i386 would need update to output thunk with local calling - convetions. */ + conventions. */ && !node->thunk.thunk_p && node->definition && !DECL_EXTERNAL (node->decl) + && !lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)) && !node->externally_visible && !node->used_from_other_partition && !node->in_other_partition @@ -211,6 +212,8 @@ cgraph_externally_visible_p (struct cgraph_node *node, if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl))) return true; + if (lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl))) + return true; if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && lookup_attribute ("dllexport", DECL_ATTRIBUTES (node->decl))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 228b885dba9..532870c90a8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-07-27 Jakub Jelinek + + * gcc.dg/attr-noipa.c: New test. + * gcc.dg/ipa/ipa-pta-18.c: New test. + * gcc.dg/ipa/ipa-sra-11.c: New test. + 2017-07-25 Michael Meissner * gcc.target/powerpc/vsx-himode.c: Delete -mvsx-small-integer diff --git a/gcc/testsuite/gcc.dg/attr-noipa.c b/gcc/testsuite/gcc.dg/attr-noipa.c new file mode 100644 index 00000000000..1d2b86894ed --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-noipa.c @@ -0,0 +1,188 @@ +/* Test the noipa attribute. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +static inline int __attribute__((noipa)) +fn1 (void) /* { dg-warning "inline function \[^\n\]* given attribute noinline" "" } */ +{ + return 1; +} + +/* Verify the function is not inlined into its caller. */ + +static __attribute__((noipa)) int +fn2 (int x, int y) +{ + return x + y; +} + +int +fn3 (int x) +{ + return fn2 (x, 0); +} + +/* { dg-final { scan-tree-dump "= fn2 \\(" "optimized" } } */ + +void fn4 (char *); + +/* Verify the function is not cloned. */ + +__attribute__((__noipa__)) static int +fn5 (int x, int y) +{ + char *p = __builtin_alloca (x + y); + fn4 (p); + return x + y; +} + +int +fn6 (int x) +{ + return fn5 (x, 2); +} + +/* { dg-final { scan-tree-dump "= fn5 \\(" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "fn5\\.constprop" "optimized" } } */ + +/* Verify we still remove unused function calls, even if they have + noipa attribute. */ + +static void fn7 (void) __attribute__((noipa)); +static void +fn7 (void) +{ +} + +/* { dg-final { scan-tree-dump-not "fn7 \\(" "optimized" } } */ + +/* Verify noipa functions are not ICF optimized. */ + +static __attribute__((noipa)) int +fn8 (int x) +{ + return x + 12; +} + +static __attribute__((noipa)) int +fn9 (int x) +{ + return x + 12; +} + +int +fn10 (int x) +{ + return fn8 (x) + fn9 (x); +} + +/* { dg-final { scan-tree-dump "fn8 \\(int" "optimized" } } */ +/* { dg-final { scan-tree-dump "fn9 \\(int" "optimized" } } */ + +/* Verify IPA-VRP is not performed. */ + +void fn11 (void); + +static int __attribute__((noipa)) +fn12 (int x) +{ + if (x < 6 || x >= 29) + fn11 (); +} + +void +fn13 (int x) +{ + fn12 (6 + (x & 15)); +} + +/* { dg-final { scan-tree-dump "fn11 \\(\\)" "optimized" } } */ + +void fn14 (void); + +__attribute__((noipa)) static int +fn15 (int x) +{ + return x & 7; +} + +int +fn16 (int x) +{ + x = fn15 (x); + if (x < 0 || x >= 7) + fn14 (); +} + +/* { dg-final { scan-tree-dump "fn14 \\(\\)" "optimized" } } */ + +/* Verify IPA BIT CP is not performed. */ + +void fn17 (void); + +__attribute__((noipa)) static int +fn18 (int x) +{ + if (x & 8) + fn17 (); +} + +void +fn19 (void) +{ + fn18 (1); + fn18 (2); + fn18 (4); + fn18 (16); + fn18 (32); + fn18 (64); +} + +/* { dg-final { scan-tree-dump "fn17 \\(\\)" "optimized" } } */ + +/* Ensure pure/const discovery is not performed. */ + +int var1; +void fn20 (void); + +__attribute__((noipa)) static int +fn21 (int x, int y) +{ + return x * y; +} + +int +fn22 (void) +{ + var1 = 7; + asm volatile ("" : "+g" (var1) : : "memory"); + int a = var1; + int b = fn21 (a, a); + if (a != var1) + fn20 (); + return b; +} + +/* { dg-final { scan-tree-dump "fn20 \\(\\)" "optimized" } } */ + +/* Verify IPA alignment propagation is not performed. */ + +static __attribute__ ((aligned(16))) char var2[32]; +void fn23 (void); + +__attribute__((noipa)) static void +fn24 (char *p) +{ + if ((((__UINTPTR_TYPE__) p) & 15) != 0) + fn23 (); + asm (""); +} + +void +fn25 (void) +{ + fn24 (var2); + fn24 (var2 + 16); +} + +/* { dg-final { scan-tree-dump "fn20 \\(\\)" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-pta-18.c b/gcc/testsuite/gcc.dg/ipa/ipa-pta-18.c new file mode 100644 index 00000000000..01b09764097 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/ipa-pta-18.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fipa-pta -fdump-ipa-pta2-details -fdump-tree-fre3-details" } */ + +static int __attribute__((noipa)) +foo (int *p, int *q) +{ + *p = 1; + *q = 0; + return *p; +} + +extern void abort (void); + +int main() +{ + int a, b; + if (foo (&a, &b) != 1) + abort (); + return 0; +} + +/* Verify we can disambiguate *p and *q in foo. */ + +/* { dg-final { scan-ipa-dump "foo.arg0 = &a" "pta2" } } */ +/* { dg-final { scan-ipa-dump "foo.arg1 = &b" "pta2" } } */ +/* { dg-final { scan-tree-dump-not "Replaced \\\*p_2\\\(D\\\) with 1" "fre3" } } */ diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-11.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-11.c new file mode 100644 index 00000000000..e91423a62fb --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-11.c @@ -0,0 +1,39 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fipa-sra -fdump-tree-eipa_sra-details" } */ + +struct bovid +{ + float red; + int green; + void *blue; +}; + +extern int printf (const char *, ...); +extern void abort (void); + +static int +__attribute__((noipa)) +ox (struct bovid cow) +{ + if (cow.green != 6) + abort (); + + printf ("green: %f\nblue: %p\nblue again: %p\n", cow.green, + cow.blue, cow.blue); + return 0; +} + +int +main (int argc, char *argv[]) +{ + struct bovid cow; + + cow.red = 7.4; + cow.green = 6; + cow.blue = &cow; + + ox (cow); + return 0; +} + +/* { dg-final { scan-tree-dump-not "About to replace expr" "eipa_sra" } } */ diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 16746e3da92..e743e35033e 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -7764,7 +7764,8 @@ refered_from_nonlocal_fn (struct cgraph_node *node, void *data) bool *nonlocal_p = (bool *)data; *nonlocal_p |= (node->used_from_other_partition || node->externally_visible - || node->force_output); + || node->force_output + || lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl))); return false; } @@ -7824,7 +7825,9 @@ ipa_pta_execute (void) constraints for parameters. */ bool nonlocal_p = (node->used_from_other_partition || node->externally_visible - || node->force_output); + || node->force_output + || lookup_attribute ("noipa", + DECL_ATTRIBUTES (node->decl))); node->call_for_symbol_thunks_and_aliases (refered_from_nonlocal_fn, &nonlocal_p, true); -- 2.30.2