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: Thu, 29 Oct 2015 14:15:07 +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>
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.
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
>>>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>
>>>
>