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. > Thanks, > Martin > >> >> Richard. >> >> >>> Thanks, >>> Martin >>> >>>> >>>>> I'm attaching v3. >>>>> >>>>> Thanks, >>>>> Martin >>>>> >>>>>> >>>>>> Otherwise looks good to me. >>>>>> >>>>>> Richard. >>>>>> >>>>>> >>>>>>> Martin >>>>>>> >>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> Martin >>>>>>>>> >>>>>>>>>> >>>>>>>>>> Richard. >>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> Martin >>>>>>>>> >>>>>>> >>>>> >>> >