This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Pass manager: add support for termination of pass list
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: Martin LiÅka <mliska at suse dot cz>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 30 Oct 2015 09:54:02 +0100
- Subject: Re: [PATCH] Pass manager: add support for termination of pass list
- Authentication-results: sourceware.org; auth=none
- References: <56263B07 dot 1010900 at suse dot cz> <CAFiYyc3PozYWSPEJvbBaQNT=UMhJTFS0nh+4AJsfRjjL2E27RA at mail dot gmail dot com> <562758A9 dot 3070309 at suse dot cz> <CAFiYyc0OWMO9ycyfds2rWOmi0j4e9pAhzEwtbKUujnK_xEwOrg at mail dot gmail dot com> <562775F3 dot 1050609 at suse dot cz> <CAFiYyc3gHUH=n7oep2Ynjdqks16rm_LmPXQPf5PNpFB5Go=RCQ at mail dot gmail dot com> <5628C262 dot 8000205 at suse dot cz> <CAFiYyc3GwQu58mmdEdWLGB3+iODREUC-KHBXhAWbz3+_4cJLNQ at mail dot gmail dot com> <562F6FC6 dot 1020200 at suse dot cz> <CAFiYyc2Qh8CjmKCwK8S=K4S33C6gR6AYf86jepzgMLPmZ5r3yA at mail dot gmail dot com> <562F9889 dot 2070704 at suse dot cz> <CAFiYyc1MZsOhgy+s9rmetE5T6w2jLdF0uR6ieuD5eBBjFaDoXg at mail dot gmail dot com> <5631EBA9 dot 2040105 at suse dot cz> <CAFiYyc1=T67BqzaKrE8=g=uf29beTY=xQUQNBBW_P0JAOov=aA at mail dot gmail dot com> <56323219 dot 4060802 at suse dot cz>
On Thu, Oct 29, 2015 at 3:50 PM, Martin LiÅka <mliska@suse.cz> wrote:
> On 10/29/2015 02:15 PM, Richard Biener wrote:
>> On Thu, Oct 29, 2015 at 10:49 AM, Martin LiÅka <mliska@suse.cz> wrote:
>>> On 10/28/2015 04:23 PM, Richard Biener wrote:
>>>> On Tue, Oct 27, 2015 at 4:30 PM, Martin LiÅka <mliska@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 <mliska@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 <mliska@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 <mliska@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 <mliska@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 <mliska@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.
>>
>> popping it once should have that effect already. If not then go
>> figure why it does not.
>
> Hello.
>
> So the problem is that init_function_start calls set_cfun:
>
> #0 set_cfun (new_cfun=0x7ffff66efbd0) at ../../gcc/function.c:4740
> #1 0x0000000000a500b8 in init_function_start (subr=0x7ffff66ec1c0) at ../../gcc/function.c:4972
> #2 0x0000000000911ee3 in cgraph_node::expand (this=0x7ffff6a0ee60) at ../../gcc/cgraphunit.c:1970
>
> So that first popping removes the function set in execute_pass_list and after that the stack is empty,
> but cfun is set to 0x7ffff66efbd0.
>
> Should I replace the second pop with set_cfun(NULL) or is it acceptable to call the popping for
> second time?
Hmm, does
@@ -2397,14 +2400,13 @@ execute_pass_list_1 (opt_pass *pass)
void
execute_pass_list (function *fn, opt_pass *pass)
{
- push_cfun (fn);
+ gcc_assert (fn == cfun);
execute_pass_list_1 (pass);
if (fn->cfg)
{
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
}
- pop_cfun ();
}
/* Write out all LTO data. */
work? All callers seem to pass cfun as fun.
> Thanks,
> Martin
>
>
>>
>> Richard.
>>
>>> Martin
>>>
>>>>
>>>>> Thanks,
>>>>> Martin
>>>>>
>>>>>>
>>>>>> Richard.
>>>>>>
>>>>>>
>>>>>>> Thanks,
>>>>>>> Martin
>>>>>>>
>>>>>>>>
>>>>>>>>> I'm attaching v3.
>>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>> Martin
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Otherwise looks good to me.
>>>>>>>>>>
>>>>>>>>>> Richard.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>> Martin
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>> Martin
>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Richard.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>> Martin
>>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>
>>>
>