public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Question about inlining and strict_aliasing
@ 2017-01-09 12:40 Martin Liška
  2017-01-09 13:34 ` Jan Hubicka
  0 siblings, 1 reply; 3+ messages in thread
From: Martin Liška @ 2017-01-09 12:40 UTC (permalink / raw)
  To: GCC Development; +Cc: Richard Biener, Jan Hubicka

[-- Attachment #1: Type: text/plain, Size: 1605 bytes --]

Hello.

I've been working on a patch that would cope with target and optimization (read PerFunction)
in a proper way. I came to following test-case (slightly modified ./gcc/testsuite/gcc.c-torture/execute/alias-1.c):

int val;

int *ptr = &val;
float *ptr2 = &val;

static
__attribute__((always_inline, optimize ("-fno-strict-aliasing")))
typepun ()
{
  *ptr2=0;
}

main()
{
  *ptr=1;
  typepun ();
  if (*ptr)
    __builtin_abort ();
}

$ gcc -O2 /tmp/always-inline.c -fdump-tree-all-details && ./a.out
Aborted (core dumped)

Problem is that einline does:

  Inlining typepun into main (always_inline).
   Estimating body: typepun/3
   Known to be false: not inlined
   size:2 time:2
Dropping flag_strict_aliasing on main:4 <<---- here is strict_aliasing drop
		Accounting size:2.00, time:2.00 on predicate:(true)

However fre1 does not still check for flag_strict_aliasing. Is it bug or not?
I did an experimental fix, but I guess there will me multiple places where the 
flag is checked.

Second question:
Current ipa-inline.c code contains question sophisticated check_{match,maybe_up,maybe_down} and
it's following by:

      /* When user added an attribute to the callee honor it.  */
      else if (lookup_attribute ("optimize", DECL_ATTRIBUTES (callee->decl))
	       && opts_for_fn (caller->decl) != opts_for_fn (callee->decl))
	{
	  e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
	  inlinable = false;
	}

I think it's very strict, as when one uses __attribute__((optimize)) with a param that matches with
command line arguments, it will return false. What if we remove the hunk?

Thanks,
Martin

[-- Attachment #2: einline.patch --]
[-- Type: text/x-patch, Size: 1599 bytes --]

diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 871fa121fd0..da38e4fab69 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -986,7 +986,7 @@ ncr_compar (const void *field1_, const void *field2_)
 static bool
 nonoverlapping_component_refs_p (const_tree x, const_tree y)
 {
-  if (!flag_strict_aliasing
+  if (!opts_for_fn (current_function_decl)->x_flag_strict_aliasing
       || !x || !y
       || TREE_CODE (x) != COMPONENT_REF
       || TREE_CODE (y) != COMPONENT_REF)
@@ -1167,7 +1167,7 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
     return false;
 
   /* Disambiguations that rely on strict aliasing rules follow.  */
-  if (!flag_strict_aliasing || !tbaa_p)
+  if (!opts_for_fn (current_function_decl)->x_flag_strict_aliasing || !tbaa_p)
     return true;
 
   ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
@@ -1334,7 +1334,7 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
     return false;
 
   /* Disambiguations that rely on strict aliasing rules follow.  */
-  if (!flag_strict_aliasing || !tbaa_p)
+  if (!opts_for_fn (current_function_decl)->x_flag_strict_aliasing || !tbaa_p)
     return true;
 
   ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
@@ -1508,7 +1508,7 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
 
   /* First defer to TBAA if possible.  */
   if (tbaa_p
-      && flag_strict_aliasing
+      && opts_for_fn (current_function_decl)->x_flag_strict_aliasing
       && !alias_sets_conflict_p (ao_ref_alias_set (ref1),
 				 ao_ref_alias_set (ref2)))
     return false;

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Question about inlining and strict_aliasing
  2017-01-09 12:40 Question about inlining and strict_aliasing Martin Liška
@ 2017-01-09 13:34 ` Jan Hubicka
  2017-01-09 14:08   ` Martin Liška
  0 siblings, 1 reply; 3+ messages in thread
From: Jan Hubicka @ 2017-01-09 13:34 UTC (permalink / raw)
  To: Martin Liška; +Cc: GCC Development, Richard Biener, Jan Hubicka

> Hello.
> 
> I've been working on a patch that would cope with target and optimization (read PerFunction)
> in a proper way. I came to following test-case (slightly modified ./gcc/testsuite/gcc.c-torture/execute/alias-1.c):
> 
> int val;
> 
> int *ptr = &val;
> float *ptr2 = &val;
> 
> static
> __attribute__((always_inline, optimize ("-fno-strict-aliasing")))
> typepun ()
> {
>   *ptr2=0;
> }
> 
> main()
> {
>   *ptr=1;
>   typepun ();
>   if (*ptr)
>     __builtin_abort ();
> }
> 
> $ gcc -O2 /tmp/always-inline.c -fdump-tree-all-details && ./a.out
> Aborted (core dumped)
> 
> Problem is that einline does:
> 
>   Inlining typepun into main (always_inline).
>    Estimating body: typepun/3
>    Known to be false: not inlined
>    size:2 time:2
> Dropping flag_strict_aliasing on main:4 <<---- here is strict_aliasing drop
> 		Accounting size:2.00, time:2.00 on predicate:(true)
> 
> However fre1 does not still check for flag_strict_aliasing. Is it bug or not?
> I did an experimental fix, but I guess there will me multiple places where the 
> flag is checked.

Aha, I think the problem is that once we modify strict aliasing of cfun, we need
to re-set the global optimization attributes, becuase those are still copies from
the original declaration.
> 
> Second question:
> Current ipa-inline.c code contains question sophisticated check_{match,maybe_up,maybe_down} and
> it's following by:
> 
>       /* When user added an attribute to the callee honor it.  */
>       else if (lookup_attribute ("optimize", DECL_ATTRIBUTES (callee->decl))
> 	       && opts_for_fn (caller->decl) != opts_for_fn (callee->decl))
> 	{
> 	  e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
> 	  inlinable = false;
> 	}
> 
> I think it's very strict, as when one uses __attribute__((optimize)) with a param that matches with
> command line arguments, it will return false. What if we remove the hunk?

I am not quite sure.  If you have function A with optimization attribute and you inline it to function b
with same command line parameters, it may enable to inline it into function C where A would not be inlined
because of the explicit optimization attribute.
If we relax this check, we will need to copy the optimization attribute from A to B at the time
we inline into B.
> 
> Thanks,
> Martin

> diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
> index 871fa121fd0..da38e4fab69 100644
> --- a/gcc/tree-ssa-alias.c
> +++ b/gcc/tree-ssa-alias.c
> @@ -986,7 +986,7 @@ ncr_compar (const void *field1_, const void *field2_)
>  static bool
>  nonoverlapping_component_refs_p (const_tree x, const_tree y)
>  {
> -  if (!flag_strict_aliasing
> +  if (!opts_for_fn (current_function_decl)->x_flag_strict_aliasing

This should not be necessary. Einline ought to update global opts.
I suppose when decl modified is cfun one needs to reset current_funcion_decl
to NULL and then set it again so the global flags changing machinery notices this
change.

Honza
t
>        || !x || !y
>        || TREE_CODE (x) != COMPONENT_REF
>        || TREE_CODE (y) != COMPONENT_REF)
> @@ -1167,7 +1167,7 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
>      return false;
>  
>    /* Disambiguations that rely on strict aliasing rules follow.  */
> -  if (!flag_strict_aliasing || !tbaa_p)
> +  if (!opts_for_fn (current_function_decl)->x_flag_strict_aliasing || !tbaa_p)
>      return true;
>  
>    ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
> @@ -1334,7 +1334,7 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
>      return false;
>  
>    /* Disambiguations that rely on strict aliasing rules follow.  */
> -  if (!flag_strict_aliasing || !tbaa_p)
> +  if (!opts_for_fn (current_function_decl)->x_flag_strict_aliasing || !tbaa_p)
>      return true;
>  
>    ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
> @@ -1508,7 +1508,7 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
>  
>    /* First defer to TBAA if possible.  */
>    if (tbaa_p
> -      && flag_strict_aliasing
> +      && opts_for_fn (current_function_decl)->x_flag_strict_aliasing
>        && !alias_sets_conflict_p (ao_ref_alias_set (ref1),
>  				 ao_ref_alias_set (ref2)))
>      return false;

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Question about inlining and strict_aliasing
  2017-01-09 13:34 ` Jan Hubicka
@ 2017-01-09 14:08   ` Martin Liška
  0 siblings, 0 replies; 3+ messages in thread
From: Martin Liška @ 2017-01-09 14:08 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: GCC Development, Richard Biener

[-- Attachment #1: Type: text/plain, Size: 4799 bytes --]

On 01/09/2017 02:34 PM, Jan Hubicka wrote:
>> Hello.
>>
>> I've been working on a patch that would cope with target and optimization (read PerFunction)
>> in a proper way. I came to following test-case (slightly modified ./gcc/testsuite/gcc.c-torture/execute/alias-1.c):
>>
>> int val;
>>
>> int *ptr = &val;
>> float *ptr2 = &val;
>>
>> static
>> __attribute__((always_inline, optimize ("-fno-strict-aliasing")))
>> typepun ()
>> {
>>   *ptr2=0;
>> }
>>
>> main()
>> {
>>   *ptr=1;
>>   typepun ();
>>   if (*ptr)
>>     __builtin_abort ();
>> }
>>
>> $ gcc -O2 /tmp/always-inline.c -fdump-tree-all-details && ./a.out
>> Aborted (core dumped)
>>
>> Problem is that einline does:
>>
>>   Inlining typepun into main (always_inline).
>>    Estimating body: typepun/3
>>    Known to be false: not inlined
>>    size:2 time:2
>> Dropping flag_strict_aliasing on main:4 <<---- here is strict_aliasing drop
>> 		Accounting size:2.00, time:2.00 on predicate:(true)
>>
>> However fre1 does not still check for flag_strict_aliasing. Is it bug or not?
>> I did an experimental fix, but I guess there will me multiple places where the 
>> flag is checked.
> 
> Aha, I think the problem is that once we modify strict aliasing of cfun, we need
> to re-set the global optimization attributes, becuase those are still copies from
> the original declaration.

Good, I prepared patch that does that and works for me. Is it stage3 material? I hope it is
as it fixes a miscompilation. Should I create PR for that?

>>
>> Second question:
>> Current ipa-inline.c code contains question sophisticated check_{match,maybe_up,maybe_down} and
>> it's following by:
>>
>>       /* When user added an attribute to the callee honor it.  */
>>       else if (lookup_attribute ("optimize", DECL_ATTRIBUTES (callee->decl))
>> 	       && opts_for_fn (caller->decl) != opts_for_fn (callee->decl))
>> 	{
>> 	  e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
>> 	  inlinable = false;
>> 	}
>>
>> I think it's very strict, as when one uses __attribute__((optimize)) with a param that matches with
>> command line arguments, it will return false. What if we remove the hunk?
> 
> I am not quite sure.  If you have function A with optimization attribute and you inline it to function b
> with same command line parameters, it may enable to inline it into function C where A would not be inlined
> because of the explicit optimization attribute.
> If we relax this check, we will need to copy the optimization attribute from A to B at the time
> we inline into B.

Can you please provide an example for that? As I've been thinking about it, both IPA inline and IPA ICF should
handle optimization flags/attributes in very similar manner as it can potentially make a divergence for -fcompare-debug

>>
>> Thanks,
>> Martin
> 
>> diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
>> index 871fa121fd0..da38e4fab69 100644
>> --- a/gcc/tree-ssa-alias.c
>> +++ b/gcc/tree-ssa-alias.c
>> @@ -986,7 +986,7 @@ ncr_compar (const void *field1_, const void *field2_)
>>  static bool
>>  nonoverlapping_component_refs_p (const_tree x, const_tree y)
>>  {
>> -  if (!flag_strict_aliasing
>> +  if (!opts_for_fn (current_function_decl)->x_flag_strict_aliasing
> 
> This should not be necessary. Einline ought to update global opts.
> I suppose when decl modified is cfun one needs to reset current_funcion_decl
> to NULL and then set it again so the global flags changing machinery notices this
> change.

Yep, fixed in the patch
Martin

> 
> Honza
> t
>>        || !x || !y
>>        || TREE_CODE (x) != COMPONENT_REF
>>        || TREE_CODE (y) != COMPONENT_REF)
>> @@ -1167,7 +1167,7 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
>>      return false;
>>  
>>    /* Disambiguations that rely on strict aliasing rules follow.  */
>> -  if (!flag_strict_aliasing || !tbaa_p)
>> +  if (!opts_for_fn (current_function_decl)->x_flag_strict_aliasing || !tbaa_p)
>>      return true;
>>  
>>    ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
>> @@ -1334,7 +1334,7 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
>>      return false;
>>  
>>    /* Disambiguations that rely on strict aliasing rules follow.  */
>> -  if (!flag_strict_aliasing || !tbaa_p)
>> +  if (!opts_for_fn (current_function_decl)->x_flag_strict_aliasing || !tbaa_p)
>>      return true;
>>  
>>    ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
>> @@ -1508,7 +1508,7 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
>>  
>>    /* First defer to TBAA if possible.  */
>>    if (tbaa_p
>> -      && flag_strict_aliasing
>> +      && opts_for_fn (current_function_decl)->x_flag_strict_aliasing
>>        && !alias_sets_conflict_p (ao_ref_alias_set (ref1),
>>  				 ao_ref_alias_set (ref2)))
>>      return false;
> 


[-- Attachment #2: einline-v2.patch --]
[-- Type: text/x-patch, Size: 2473 bytes --]

diff --git a/gcc/function.c b/gcc/function.c
index 7fde96adbe3..f625489205b 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -4811,9 +4811,9 @@ invoke_set_current_function_hook (tree fndecl)
 /* cfun should never be set directly; use this function.  */
 
 void
-set_cfun (struct function *new_cfun)
+set_cfun (struct function *new_cfun, bool force)
 {
-  if (cfun != new_cfun)
+  if (cfun != new_cfun || force)
     {
       cfun = new_cfun;
       invoke_set_current_function_hook (new_cfun ? new_cfun->decl : NULL_TREE);
diff --git a/gcc/function.h b/gcc/function.h
index fb3cbbc3346..fb8f57ae385 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -613,7 +613,7 @@ extern tree block_chainon (tree, tree);
 extern void number_blocks (tree);
 
 /* cfun shouldn't be set directly; use one of these functions instead.  */
-extern void set_cfun (struct function *new_cfun);
+extern void set_cfun (struct function *new_cfun, bool force = false);
 extern void push_cfun (struct function *new_cfun);
 extern void pop_cfun (void);
 
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
index 7725fadd6d8..a8e73cd6967 100644
--- a/gcc/ipa-inline-transform.c
+++ b/gcc/ipa-inline-transform.c
@@ -340,6 +340,8 @@ inline_call (struct cgraph_edge *e, bool update_original,
   if (DECL_FUNCTION_PERSONALITY (callee->decl))
     DECL_FUNCTION_PERSONALITY (to->decl)
       = DECL_FUNCTION_PERSONALITY (callee->decl);
+
+  bool reload_optimization_node = false;
   if (!opt_for_fn (callee->decl, flag_strict_aliasing)
       && opt_for_fn (to->decl, flag_strict_aliasing))
     {
@@ -352,6 +354,7 @@ inline_call (struct cgraph_edge *e, bool update_original,
 		 to->name (), to->order);
       DECL_FUNCTION_SPECIFIC_OPTIMIZATION (to->decl)
 	 = build_optimization_node (&opts);
+      reload_optimization_node = true;
     }
 
   inline_summary *caller_info = inline_summaries->get (to);
@@ -412,9 +415,14 @@ inline_call (struct cgraph_edge *e, bool update_original,
 		     callee->name (), callee->order, to->name (), to->order);
 	  DECL_FUNCTION_SPECIFIC_OPTIMIZATION (to->decl)
 	     = build_optimization_node (&opts);
+	  reload_optimization_node = true;
 	}
     }
 
+  /* Reload global optimization flags.  */
+  if (reload_optimization_node && DECL_STRUCT_FUNCTION (to->decl) == cfun)
+    set_cfun (cfun, true);
+
   /* If aliases are involved, redirect edge to the actual destination and
      possibly remove the aliases.  */
   if (e->callee != callee)

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-01-09 14:08 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-09 12:40 Question about inlining and strict_aliasing Martin Liška
2017-01-09 13:34 ` Jan Hubicka
2017-01-09 14:08   ` Martin Liška

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).