Commit 036ea399 by Jakub Jelinek Committed by Jakub Jelinek

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
parent 2443509b
2017-07-27 Jakub Jelinek <jakub@redhat.com>
* 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 <apinski@cavium.com>
* config/aarch64/aarch64.c (thunderx_vector_cost): Decrease cost of
......
......@@ -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))
......
2017-07-27 Jakub Jelinek <jakub@redhat.com>
* c-attribs.c (c_common_attribute_table): Add noipa attribute.
(handle_noipa_attribute): New function.
2017-07-07 Torsten Duwe <duwe@suse.de>
* c-attribs.c (c_common_attribute_table): Add entry for
......
......@@ -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,
......@@ -704,6 +707,21 @@ handle_stack_protect_attribute (tree *node, tree name, tree, int,
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)
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
else
DECL_ATTRIBUTES (*node)
= tree_cons (get_identifier ("stack_protect"),
......
......@@ -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;
......
......@@ -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
......
......@@ -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 ();
......
......@@ -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)))
......
2017-07-27 Jakub Jelinek <jakub@redhat.com>
* 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 <meissner@linux.vnet.ibm.com>
* gcc.target/powerpc/vsx-himode.c: Delete -mvsx-small-integer
......
/* 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" } } */
/* { 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" } } */
/* { 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" } } */
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment