> On Aug 16, 2021, at 10:08 AM, Richard Biener <rguent...@suse.de> wrote: > > On August 16, 2021 4:48:16 PM GMT+02:00, Qing Zhao <qing.z...@oracle.com> > wrote: >> >> >>> On Aug 16, 2021, at 2:12 AM, Richard Biener <rguent...@suse.de> wrote: >>> >>> On Wed, 11 Aug 2021, Qing Zhao wrote: >>> >>>> Hi, >>>> >>>> I finally decided to take another approach to resolve this issue, it >>>> resolved all the potential issues with the “address taken” auto variable. >>>> >>>> The basic idea is to avoid generating the temporary variable in the >>>> beginning. >>>> As you mentioned, "The reason is that alt_reloc is memory (because it is >>>> address taken) and that GIMPLE says that register typed stores >>>> need to use a is_gimple_val RHS which the call is not.” >>>> In order to avoid generating the temporary variable for “address taken” >>>> auto variable, I updated the utility routine “is_gimple_val” as following: >>>> >>>> diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c >>>> index a2563a45c37d..d5ef1aef8cea 100644 >>>> --- a/gcc/gimple-expr.c >>>> +++ b/gcc/gimple-expr.c >>>> @@ -787,8 +787,20 @@ is_gimple_reg (tree t) >>>> return !DECL_NOT_GIMPLE_REG_P (t); >>>> } >>>> >>>> +/* Return true if T is a call to .DEFERRED_INIT internal function. */ >>>> +static bool >>>> +is_deferred_init_call (tree t) >>>> +{ >>>> + if (TREE_CODE (t) == CALL_EXPR >>>> + && CALL_EXPR_IFN (t) == IFN_DEFERRED_INIT) >>>> + return true; >>>> + return false; >>>> +} >>>> + >>>> >>>> -/* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant. >>>> */ >>>> +/* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant, >>>> + or a call to .DEFERRED_INIT internal function because the call to >>>> + .DEFERRED_INIT will eventually be expanded as a constant. */ >>>> >>>> bool >>>> is_gimple_val (tree t) >>>> @@ -799,7 +811,8 @@ is_gimple_val (tree t) >>>> && !is_gimple_reg (t)) >>>> return false; >>>> >>>> - return (is_gimple_variable (t) || is_gimple_min_invariant (t)); >>>> + return (is_gimple_variable (t) || is_gimple_min_invariant (t) >>>> + || is_deferred_init_call (t)); >>>> } >>>> >>>> With this change, the temporary variable will not be created for “address >>>> taken” auto variable, and uninitialized analysis does not need any change. >>>> Everything works well. >>>> >>>> And I believe that treating “call to .DEFERRED_INIT” as “is_gimple_val” is >>>> reasonable since this call actually is a constant. >>>> >>>> Let me know if you have any objection on this solution. >>> >>> Yeah, I object to this solution. >> >> Can you explain what’s the major issue for this solution? > > It punches a hole into the GIMPLE IL which is very likely incomplete and will > cause issues elsewhere. In particular the corresponding type check is missing > and not computable since the RHS of this call isn't separately available. > > If you go down this route then you should have added a new constant class > tree code instead of an internal function call.
Okay. I see. > >> To me, treating “call to .DEFERRED_INIT” as “is_gimple_val” is reasonable >> since this call actually is a constant. > > Sure, but it's not represented as such. Thank you!. Qing > > Richard. > >> Thanks. >> >> Qing >>> Richard. >>> >>>> thanks. >>>> >>>> Qing >>>> >>>>> On Aug 11, 2021, at 3:30 PM, Qing Zhao via Gcc-patches >>>>> <gcc-patches@gcc.gnu.org> wrote: >>>>> >>>>> Hi, >>>>> >>>>> I met another issue for “address taken” auto variable, see below for >>>>> details: >>>>> >>>>> **** the testing case: (gcc/testsuite/gcc.dg/uninit-16.c) >>>>> >>>>> int foo, bar; >>>>> >>>>> static >>>>> void decode_reloc(int reloc, int *is_alt) >>>>> { >>>>> if (reloc >= 20) >>>>> *is_alt = 1; >>>>> else if (reloc >= 10) >>>>> *is_alt = 0; >>>>> } >>>>> >>>>> void testfunc() >>>>> { >>>>> int alt_reloc; >>>>> >>>>> decode_reloc(foo, &alt_reloc); >>>>> >>>>> if (alt_reloc) /* { dg-warning "may be used uninitialized" } */ >>>>> bar = 42; >>>>> } >>>>> >>>>> ****When compiled with -ftrivial-auto-var-init=zero -O2 -Wuninitialized >>>>> -fdump-tree-all: >>>>> >>>>> .*************gimple dump: >>>>> >>>>> void testfunc () >>>>> { >>>>> int alt_reloc; >>>>> >>>>> try >>>>> { >>>>> _1 = .DEFERRED_INIT (4, 2, 0); >>>>> alt_reloc = _1; >>>>> foo.0_2 = foo; >>>>> decode_reloc (foo.0_2, &alt_reloc); >>>>> alt_reloc.1_3 = alt_reloc; >>>>> if (alt_reloc.1_3 != 0) goto <D.1952>; else goto <D.1953>; >>>>> <D.1952>: >>>>> bar = 42; >>>>> <D.1953>: >>>>> } >>>>> finally >>>>> { >>>>> alt_reloc = {CLOBBER}; >>>>> } >>>>> } >>>>> >>>>> **************fre1 dump: >>>>> >>>>> void testfunc () >>>>> { >>>>> int alt_reloc; >>>>> int _1; >>>>> int foo.0_2; >>>>> >>>>> <bb 2> : >>>>> _1 = .DEFERRED_INIT (4, 2, 0); >>>>> foo.0_2 = foo; >>>>> if (foo.0_2 > 19) >>>>> goto <bb 3>; [50.00%] >>>>> else >>>>> goto <bb 4>; [50.00%] >>>>> >>>>> <bb 3> : >>>>> goto <bb 7>; [100.00%] >>>>> >>>>> <bb 4> : >>>>> if (foo.0_2 > 9) >>>>> goto <bb 5>; [50.00%] >>>>> else >>>>> goto <bb 6>; [50.00%] >>>>> >>>>> <bb 5> : >>>>> goto <bb 8>; [100.00%] >>>>> >>>>> <bb 6> : >>>>> if (_1 != 0) >>>>> goto <bb 7>; [INV] >>>>> else >>>>> goto <bb 8>; [INV] >>>>> >>>>> <bb 7> : >>>>> bar = 42; >>>>> >>>>> <bb 8> : >>>>> return; >>>>> >>>>> } >>>>> >>>>> From the above IR file after “FRE”, we can see that the major issue with >>>>> this IR is: >>>>> >>>>> The address taken auto variable “alt_reloc” has been completely replaced >>>>> by the temporary variable “_1” in all >>>>> the uses of the original “alt_reloc”. >>>>> >>>>> The major problem with such IR is, during uninitialized analysis phase, >>>>> the original use of “alt_reloc” disappeared completely. >>>>> So, the warning cannot be reported. >>>>> >>>>> >>>>> My questions: >>>>> >>>>> 1. Is it possible to get the original “alt_reloc” through the temporary >>>>> variable “_1” with some available information recorded in the IR? >>>>> 2. If not, then we have to record the relationship between “alt_reloc” >>>>> and “_1” when the original “alt_reloc” is replaced by “_1” and get such >>>>> relationship during >>>>> Uninitialized analysis phase. Is this doable? >>>>> 3. Looks like that for “address taken” auto variable, if we have to >>>>> introduce a new temporary variable and split the call to .DEFERRED_INIT >>>>> into two: >>>>> >>>>> temp = .DEFERRED_INIT (4, 2, 0); >>>>> alt_reloc = temp; >>>>> >>>>> More issues might possible. >>>>> >>>>> Any comments and suggestions on this issue? >>>>> >>>>> Qing >>>>> >>>>> j >>>>>> On Aug 11, 2021, at 11:55 AM, Richard Biener <rguent...@suse.de> wrote: >>>>>> >>>>>> On August 11, 2021 6:22:00 PM GMT+02:00, Qing Zhao >>>>>> <qing.z...@oracle.com> wrote: >>>>>>> >>>>>>> >>>>>>>> On Aug 11, 2021, at 10:53 AM, Richard Biener <rguent...@suse.de> wrote: >>>>>>>> >>>>>>>> On August 11, 2021 5:30:40 PM GMT+02:00, Qing Zhao >>>>>>>> <qing.z...@oracle.com> wrote: >>>>>>>>> I modified the routine “gimple_add_init_for_auto_var” as the >>>>>>>>> following: >>>>>>>>> ==== >>>>>>>>> /* Generate initialization to automatic variable DECL based on >>>>>>>>> INIT_TYPE. >>>>>>>>> Build a call to internal const function DEFERRED_INIT: >>>>>>>>> 1st argument: SIZE of the DECL; >>>>>>>>> 2nd argument: INIT_TYPE; >>>>>>>>> 3rd argument: IS_VLA, 0 NO, 1 YES; >>>>>>>>> >>>>>>>>> as DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, IS_VLA). */ >>>>>>>>> static void >>>>>>>>> gimple_add_init_for_auto_var (tree decl, >>>>>>>>> enum auto_init_type init_type, >>>>>>>>> bool is_vla, >>>>>>>>> gimple_seq *seq_p) >>>>>>>>> { >>>>>>>>> gcc_assert (VAR_P (decl) && !DECL_EXTERNAL (decl) && !TREE_STATIC >>>>>>>>> (decl)); >>>>>>>>> gcc_assert (init_type > AUTO_INIT_UNINITIALIZED); >>>>>>>>> tree decl_size = TYPE_SIZE_UNIT (TREE_TYPE (decl)); >>>>>>>>> >>>>>>>>> tree init_type_node >>>>>>>>> = build_int_cst (integer_type_node, (int) init_type); >>>>>>>>> tree is_vla_node >>>>>>>>> = build_int_cst (integer_type_node, (int) is_vla); >>>>>>>>> >>>>>>>>> tree call = build_call_expr_internal_loc (UNKNOWN_LOCATION, >>>>>>>>> IFN_DEFERRED_INIT, >>>>>>>>> TREE_TYPE (decl), 3, >>>>>>>>> decl_size, init_type_node, >>>>>>>>> is_vla_node); >>>>>>>>> >>>>>>>>> /* If this DECL is a VLA, a temporary address variable for it has been >>>>>>>>> created, the replacement for DECL is recorded in DECL_VALUE_EXPR >>>>>>>>> (decl), >>>>>>>>> we should use it as the LHS of the call. */ >>>>>>>>> >>>>>>>>> tree lhs_call >>>>>>>>> = is_vla ? DECL_VALUE_EXPR (decl) : decl; >>>>>>>>> gimplify_assign (lhs_call, call, seq_p); >>>>>>>>> } >>>>>>>>> >>>>>>>>> With this change, the current issue is resolved, the gimple dump now >>>>>>>>> is: >>>>>>>>> >>>>>>>>> (*arr.1) = .DEFERRED_INIT (D.1952, 2, 1); >>>>>>>>> >>>>>>>>> However, there is another new issue: >>>>>>>>> >>>>>>>>> For the following testing case: >>>>>>>>> >>>>>>>>> ====== >>>>>>>>> [opc@qinzhao-ol8u3-x86 gcc]$ cat t.c >>>>>>>>> int bar; >>>>>>>>> >>>>>>>>> extern void decode_reloc(int *); >>>>>>>>> >>>>>>>>> void testfunc() >>>>>>>>> { >>>>>>>>> int alt_reloc; >>>>>>>>> >>>>>>>>> decode_reloc(&alt_reloc); >>>>>>>>> >>>>>>>>> if (alt_reloc) /* { dg-warning "may be used uninitialized" } */ >>>>>>>>> bar = 42; >>>>>>>>> } >>>>>>>>> ===== >>>>>>>>> >>>>>>>>> In the above, the auto var “alt_reloc” is address taken, then the >>>>>>>>> gimple dump for it when compiled with -ftrivial-auto-var-init=zero is: >>>>>>>>> >>>>>>>>> void testfunc () >>>>>>>>> { >>>>>>>>> int alt_reloc; >>>>>>>>> >>>>>>>>> try >>>>>>>>> { >>>>>>>>> _1 = .DEFERRED_INIT (4, 2, 0); >>>>>>>>> alt_reloc = _1; >>>>>>>>> decode_reloc (&alt_reloc); >>>>>>>>> alt_reloc.0_2 = alt_reloc; >>>>>>>>> if (alt_reloc.0_2 != 0) goto <D.1949>; else goto <D.1950>; >>>>>>>>> <D.1949>: >>>>>>>>> bar = 42; >>>>>>>>> <D.1950>: >>>>>>>>> } >>>>>>>>> finally >>>>>>>>> { >>>>>>>>> alt_reloc = {CLOBBER}; >>>>>>>>> } >>>>>>>>> } >>>>>>>>> >>>>>>>>> I.e, instead of the expected IR: >>>>>>>>> >>>>>>>>> alt_reloc = .DEFERRED_INIT (4, 2, 0); >>>>>>>>> >>>>>>>>> We got the following: >>>>>>>>> >>>>>>>>> _1 = .DEFERRED_INIT (4, 2, 0); >>>>>>>>> alt_reloc = _1; >>>>>>>>> >>>>>>>>> I guess the temp “_1” is created because “alt_reloc” is address >>>>>>>>> taken. >>>>>>>> >>>>>>>> Yes and no. The reason is that alt_reloc is memory (because it is >>>>>>>> address taken) and that GIMPLE says that register typed stores need to >>>>>>>> use a is_gimple_val RHS which the call is not. >>>>>>> >>>>>>> Okay. >>>>>>>> >>>>>>>>> My questions: >>>>>>>>> >>>>>>>>> Shall we accept such IR for .DEFERRED_INIT purpose when the auto var >>>>>>>>> is address taken? >>>>>>>> >>>>>>>> I think so. Note it doesn't necessarily need address taking but any >>>>>>>> other reason that prevents SSA rewriting the variable suffices. >>>>>>> >>>>>>> You mean, in addition to “address taken”, there are other situations >>>>>>> that will introduce such IR: >>>>>>> >>>>>>> temp = .DEFERRED_INIT(); >>>>>>> auto_var = temp; >>>>>>> >>>>>>> So, such IR is unavoidable and we have to handle it? >>>>>> >>>>>> Yes. >>>>>> >>>>>>> If we have to handle it, what’ the best way to do it? >>>>>>> >>>>>>> The solution in my mind is: >>>>>>> 1. During uninitialized analysis phase, following the data flow to >>>>>>> connect .DEFERRED_INIT to “auto_var”, and then decide that “auto_var” >>>>>>> is uninitialized. >>>>>> >>>>>> Yes. Basically if there's an artificial variable auto initialized you >>>>>> have to look at its uses. >>>>>> >>>>>>> 2. During RTL expansion, following the data flow to connect >>>>>>> .DEFERRED_INIT to “auto_var”, and then delete “temp”, and then expand >>>>>>> .DEFERRED_INIT to auto_var. >>>>>> >>>>>> That shouldn't be necessary. You'd initialize a temporary register which >>>>>> is then copied to the real variable. That's good enough and should be >>>>>> optimized by the RTL pipeline. >>>>>> >>>>>>> Let me know your comments and suggestions on this. >>>>>>> >>>>>>> >>>>>>>> >>>>>>>> The only other option is to force. DEFERED_INIT making the LHS address >>>>>>>> taken which I think could be achieved by passing it the address as >>>>>>>> argument instead of having a LHS. But let's not go down this route - >>>>>>>> it will have quite bad behavior on alias analysis and optimization. >>>>>>> >>>>>>> Okay. >>>>>>> >>>>>>> Qing >>>>>>>> >>>>>>>>> If so, “uninitialized analysis” phase need to be further adjusted to >>>>>>>>> specially handle such IR. >>>>>>>>> >>>>>>>>> If not, what should we do when the auto var is address taken? >>>> >>>> >>> >>> -- >>> Richard Biener <rguent...@suse.de> >>> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, >>> Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg) >> >