On 10/28/2015 04:23 PM, Richard Biener wrote:
> On Tue, Oct 27, 2015 at 4:30 PM, Martin Liška <mli...@suse.cz> wrote:
>> On 10/27/2015 03:49 PM, Richard Biener wrote:
>>> On Tue, Oct 27, 2015 at 1:36 PM, Martin Liška <mli...@suse.cz> wrote:
>>>> On 10/26/2015 02:48 PM, Richard Biener wrote:
>>>>> On Thu, Oct 22, 2015 at 1:02 PM, Martin Liška <mli...@suse.cz> wrote:
>>>>>> On 10/21/2015 04:06 PM, Richard Biener wrote:
>>>>>>> On Wed, Oct 21, 2015 at 1:24 PM, Martin Liška <mli...@suse.cz> wrote:
>>>>>>>> On 10/21/2015 11:59 AM, Richard Biener wrote:
>>>>>>>>> On Wed, Oct 21, 2015 at 11:19 AM, Martin Liška <mli...@suse.cz> wrote:
>>>>>>>>>> On 10/20/2015 03:39 PM, Richard Biener wrote:
>>>>>>>>>>> On Tue, Oct 20, 2015 at 3:00 PM, Martin Liška <mli...@suse.cz> 
>>>>>>>>>>> wrote:
>>>>>>>>>>>> Hello.
>>>>>>>>>>>>
>>>>>>>>>>>> As part of upcoming merge of HSA branch, we would like to have 
>>>>>>>>>>>> possibility to terminate
>>>>>>>>>>>> pass manager after execution of the HSA generation pass. The HSA 
>>>>>>>>>>>> back-end is implemented
>>>>>>>>>>>> as a tree pass that directly emits HSAIL from gimple tree 
>>>>>>>>>>>> representation. The pass operates
>>>>>>>>>>>> on clones created by HSA IPA pass and the pass manager should stop 
>>>>>>>>>>>> execution of further
>>>>>>>>>>>> RTL passes.
>>>>>>>>>>>>
>>>>>>>>>>>> Suggested patch survives bootstrap and regression tests on 
>>>>>>>>>>>> x86_64-linux-pc.
>>>>>>>>>>>>
>>>>>>>>>>>> What do you think about it?
>>>>>>>>>>>
>>>>>>>>>>> Are you sure it works this way?
>>>>>>>>>>>
>>>>>>>>>>> Btw, you will miss executing of all the cleanup passes that will
>>>>>>>>>>> eventually free memory
>>>>>>>>>>> associated with the function.  So I'd rather support a
>>>>>>>>>>> TODO_discard_function which
>>>>>>>>>>> should basically release the body from the cgraph.
>>>>>>>>>>
>>>>>>>>>> Hi.
>>>>>>>>>>
>>>>>>>>>> Agree with you that I should execute all TODOs, which can be easily 
>>>>>>>>>> done.
>>>>>>>>>> However, if I just try to introduce the suggested TODO and handle it 
>>>>>>>>>> properly
>>>>>>>>>> by calling cgraph_node::release_body, then for instance 
>>>>>>>>>> fn->gimple_df, fn->cfg are
>>>>>>>>>> released and I hit ICEs on many places.
>>>>>>>>>>
>>>>>>>>>> Stopping the pass manager looks necessary, or do I miss something?
>>>>>>>>>
>>>>>>>>> "Stopping the pass manager" is necessary after TODO_discard_function, 
>>>>>>>>> yes.
>>>>>>>>> But that may be simply done via a has_body () check then?
>>>>>>>>
>>>>>>>> Thanks, there's second version of the patch. I'm going to start 
>>>>>>>> regression tests.
>>>>>>>
>>>>>>> As release_body () will free cfun you should pop_cfun () before
>>>>>>> calling it (and thus
>>>>>>
>>>>>> Well, release_function_body calls both push & pop, so I think calling pop
>>>>>> before cgraph_node::release_body is not necessary.
>>>>>
>>>>> (ugh).
>>>>>
>>>>>> If tried to call pop_cfun before cgraph_node::release_body, I have cfun 
>>>>>> still
>>>>>> pointing to the same (function *) (which is gcc_freed, but cfun != NULL).
>>>>>
>>>>> Hmm, I meant to call pop_cfun then after it (unless you want to fix the 
>>>>> above,
>>>>> none of the freeing functions should techincally need 'cfun', just add
>>>>> 'fn' parameters ...).
>>>>>
>>>>> I expected pop_cfun to eventually set cfun to NULL if it popped the
>>>>> "last" cfun.  Why
>>>>> doesn't it do that?
>>>>>
>>>>>>> drop its modification).  Also TODO_discard_functiuon should be only set 
>>>>>>> for
>>>>>>> local passes thus you should probably add a gcc_assert (cfun).
>>>>>>> I'd move its handling earlier, definitely before the ggc_collect, 
>>>>>>> eventually
>>>>>>> before the pass_fini_dump_file () (do we want a last dump of the
>>>>>>> function or not?).
>>>>>>
>>>>>> Fully agree, moved here.
>>>>>>
>>>>>>>
>>>>>>> @@ -2397,6 +2410,10 @@ execute_pass_list_1 (opt_pass *pass)
>>>>>>>      {
>>>>>>>        gcc_assert (pass->type == GIMPLE_PASS
>>>>>>>                   || pass->type == RTL_PASS);
>>>>>>> +
>>>>>>> +
>>>>>>> +      if (!gimple_has_body_p (current_function_decl))
>>>>>>> +       return;
>>>>>>>
>>>>>>> too much vertical space.  With popping cfun before releasing the body 
>>>>>>> the check
>>>>>>> might just become if (!cfun) and
>>>>>>
>>>>>> As mentioned above, as release body is symmetric (calling push & pop), 
>>>>>> the suggested
>>>>>> guard will not work.
>>>>>
>>>>> I suggest to fix it.  If it calls push/pop it should leave with the
>>>>> original cfun, popping again
>>>>> should make it NULL?
>>>>>
>>>>>>>
>>>>>>> @@ -2409,7 +2426,7 @@ execute_pass_list (function *fn, opt_pass *pass)
>>>>>>>  {
>>>>>>>    push_cfun (fn);
>>>>>>>    execute_pass_list_1 (pass);
>>>>>>> -  if (fn->cfg)
>>>>>>> +  if (gimple_has_body_p (current_function_decl) && fn->cfg)
>>>>>>>      {
>>>>>>>        free_dominance_info (CDI_DOMINATORS);
>>>>>>>        free_dominance_info (CDI_POST_DOMINATORS);
>>>>>>>
>>>>>>> here you'd need to guard the pop_cfun call on cfun != NULL.  IMHO it's 
>>>>>>> better
>>>>>>> to not let cfun point to deallocated data.
>>>>>>
>>>>>> As I've read the code, since we gcc_free 'struct function', one can just 
>>>>>> rely on
>>>>>> gimple_has_body_p (current_function_decl) as it correctly realizes that
>>>>>> DECL_STRUCT_FUNCTION (current_function_decl) == NULL.
>>>>>
>>>>> I'm sure that with some GC checking ggc_free makes them #deadbeef or so:
>>>>>
>>>>> void
>>>>> ggc_free (void *p)
>>>>> {
>>>>> ...
>>>>> #ifdef ENABLE_GC_CHECKING
>>>>>   /* Poison the data, to indicate the data is garbage.  */
>>>>>   VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (p, size));
>>>>>   memset (p, 0xa5, size);
>>>>> #endif
>>>>>
>>>>> so I don't think that's a good thing to rely on ;)
>>>>>
>>>>> Richard.
>>>>
>>>> Hi Richi, fully agree that relying of 0xdeadbeaf is not good.
>>>> I'm sending quite simple patch v4 where I enable popping up
>>>> the stack to eventually set cfun = current_function_decl = NULL.
>>>>
>>>> Question of using push & pop in cgraph_node::release_body should
>>>> be orthogonal as there are other places where the function is used.
>>>>
>>>> What do you think about the patch?
>>>
>>> @@ -4763,6 +4763,13 @@ push_cfun (struct function *new_cfun)
>>>  void
>>>  pop_cfun (void)
>>>  {
>>> +  if (cfun_stack.is_empty ())
>>> +    {
>>> +      set_cfun (NULL);
>>> +      current_function_decl = NULL_TREE;
>>> +      return;
>>> +    }
>>> +
>>>
>>> I'd like to avoid this by...
>>>
>>> @@ -2405,11 +2428,12 @@ execute_pass_list (function *fn, opt_pass *pass)
>>>  {
>>>    push_cfun (fn);
>>>    execute_pass_list_1 (pass);
>>> -  if (fn->cfg)
>>> +  if (current_function_decl && fn->cfg)
>>>      {
>>>        free_dominance_info (CDI_DOMINATORS);
>>>        free_dominance_info (CDI_POST_DOMINATORS);
>>>      }
>>> +
>>>    pop_cfun ();
>>>
>>> making this conditional on if (cfun).  Btw, please check cfun against NULL,
>>> not current_function_decl.
>>
>> Done.
>>
>>>
>>> +      if (dom_info_available_p (CDI_POST_DOMINATORS))
>>> +       free_dominance_info (CDI_POST_DOMINATORS);
>>> +
>>> +      /* Pop function inserted in execute_pass_list.  */
>>> +      pop_cfun ();
>>> +
>>> +      cgraph_node::get (cfun->decl)->release_body ();
>>> +
>>> +      /* Set cfun and current_function_decl to be NULL.  */
>>> +      pop_cfun ();
>>> +    }
>>>
>>> this also looks weird.  Because you pop_cfun and then access cfun and
>>> then you pop cfun again?  I'd say most clean would be
>>>
>>> +      if (dom_info_available_p (CDI_POST_DOMINATORS))
>>> +       free_dominance_info (CDI_POST_DOMINATORS);
>>> +       tree fn = cfun->decl;
>>>          pop_cfun ();
>>>         cgraph_node::get (fn)->release_body ();
>>>       }
>>>
>>> or does the comment say that the current function is on the stack
>>> twice somehow?  How can that happen?
>>
>> You are right, your change applied.
>>
>> Sending V5. If OK, I'll create corresponding changelog entry
>> and run regression tests.
> 
> You still have
> 
> @@ -4763,6 +4763,13 @@ push_cfun (struct function *new_cfun)
>  void
>  pop_cfun (void)
>  {
> +  if (cfun_stack.is_empty ())
> +    {
> +      set_cfun (NULL);
> +      current_function_decl = NULL_TREE;
> +      return;
> +    }
> 
> and popping of cfun twice in execute_one_pass.
> 
> Richard.

Right and that's the way how I set current_function_decl = cfun = NULL
(both pop_cfun are commented what they do).
As the popping is done at the end of execute_pass_list and having empty
stack just sets to NULL, it should be fine.

Martin

> 
>> Thanks,
>> Martin
>>
>>>
>>> Richard.
>>>
>>>
>>>> Thanks,
>>>> Martin
>>>>
>>>>>
>>>>>> I'm attaching v3.
>>>>>>
>>>>>> Thanks,
>>>>>> Martin
>>>>>>
>>>>>>>
>>>>>>> Otherwise looks good to me.
>>>>>>>
>>>>>>> Richard.
>>>>>>>
>>>>>>>
>>>>>>>> Martin
>>>>>>>>
>>>>>>>>>
>>>>>>>>>> Thanks,
>>>>>>>>>> Martin
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Richard.
>>>>>>>>>>>
>>>>>>>>>>>> Thanks,
>>>>>>>>>>>> Martin
>>>>>>>>>>
>>>>>>>>
>>>>>>
>>>>
>>

Reply via email to