Hi, Richard, Could you please comment on the following approach:
Instead of adding the zero-initializer quite late at the pass “pass_expand”, we can add it as early as during gimplification. However, we will mark these new added zero-initializers as “artificial”. And passing this “artificial” information to “pass_early_warn_uninitialized” and “pass_late_warn_uninitialized”, in these two uninitialized variable analysis passes, (i.e., in tree-sea-uninit.c) We will update the checking on “ssa_undefined_value_p” to consider “artificial” zero-initializers. (i.e, if the def_stmt is marked with “artificial”, then it’s a undefined value). With such approach, we should be able to address all those conflicts. Do you see any obvious issue with this approach? Thanks a lot for your help. Qing > On Nov 25, 2020, at 3:11 AM, Richard Biener <richard.guent...@gmail.com> > wrote: >> >> >> I am planing to add a new phase immediately after >> “pass_late_warn_uninitialized” to initialize all auto-variables that are >> not explicitly initialized in the declaration, the basic idea is following: >> >> ** The proposal: >> >> A. add a new GCC option: (same name and meaning as CLANG) >> -ftrivial-auto-var-init=[pattern|zero], similar pattern init as CLANG; >> >> B. add a new attribute for variable: >> __attribute((uninitialized) >> the marked variable is uninitialized intentionaly for performance purpose. >> >> C. The implementation needs to keep the current static warning on >> uninitialized >> variables untouched in order to avoid "forking the language". >> >> >> ** The implementation: >> >> There are two major requirements for the implementation: >> >> 1. all auto-variables that do not have an explicit initializer should be >> initialized to >> zero by this option. (Same behavior as CLANG) >> >> 2. keep the current static warning on uninitialized variables untouched. >> >> In order to satisfy 1, we should check whether an auto-variable has >> initializer >> or not; >> In order to satisfy 2, we should add this new transformation after >> "pass_late_warn_uninitialized". >> >> So, we should be able to check whether an auto-variable has initializer or >> not after “pass_late_warn_uninitialized”, >> If Not, then insert an initialization for it. >> >> For this purpose, I guess that “FOR_EACH_LOCAL_DECL” might be better? >> >> >> I think both as long as they are source-level auto-variables. Then which one >> is better? >> >> >> Another issue is, in order to check whether an auto-variable has >> initializer, I plan to add a new bit in “decl_common” as: >> /* In a VAR_DECL, this is DECL_IS_INITIALIZED. */ >> unsigned decl_is_initialized :1; >> >> /* IN VAR_DECL, set when the decl is initialized at the declaration. */ >> #define DECL_IS_INITIALIZED(NODE) \ >> (DECL_COMMON_CHECK (NODE)->decl_common.decl_is_initialized) >> >> set this bit when setting DECL_INITIAL for the variables in FE. then keep it >> even though DECL_INITIAL might be NULLed. >> >> >> For locals it would be more reliable to set this flag-Wmaybe-uninitialized. >> >> >> You mean I can set the flag “DECL_IS_INITIALIZED (decl)” inside the routine >> “gimpley_decl_expr” (gimplify.c) as following: >> >> if (VAR_P (decl) && !DECL_EXTERNAL (decl)) >> { >> tree init = DECL_INITIAL (decl); >> ... >> if (init && init != error_mark_node) >> { >> if (!TREE_STATIC (decl)) >> { >> DECL_IS_INITIALIZED(decl) = 1; >> } >> >> Is this enough for all Frontends? Are there other places that I need to >> maintain this bit? >> >> >> >> Do you have any comment and suggestions? >> >> >> As said above - do you want to cover registers as well as locals? >> >> >> All the locals from the source-code point of view should be covered. (From >> my study so far, looks like that Clang adds that phase in FE). >> If GCC adds this phase in FE, then the following design requirement >> >> C. The implementation needs to keep the current static warning on >> uninitialized >> variables untouched in order to avoid "forking the language”. >> >> cannot be satisfied. Since gcc’s uninitialized variables analysis is >> applied quite late. >> >> So, we have to add this new phase after “pass_late_warn_uninitialized”. >> >> I'd do >> the actual zeroing during RTL expansion instead since otherwise you >> have to figure youself whether a local is actually used (see >> expand_stack_vars) >> >> >> Adding this new transformation during RTL expansion is okay. I will check >> on this in more details to see how to add it to RTL expansion phase. >> >> >> Note that optimization will already made have use of "uninitialized" state >> of locals so depending on what the actual goal is here "late" may be too >> late. >> >> >> This is a really good point… >> >> In order to avoid optimization to use the “uninitialized” state of locals, >> we should add the zeroing phase as early as possible (adding it in FE might >> be best >> for this issue). However, if we have to met the following requirement: > > So is optimization supposed to pick up zero or is it supposed to act > as if the initializer > is unknown? > >> C. The implementation needs to keep the current static warning on >> uninitialized >> variables untouched in order to avoid "forking the language”. >> >> We have to move the new phase after all the uninitialized analysis is done >> in order to avoid “forking the language”. >> >> So, this is a problem that is not easy to resolve. > > Indeed, those are conflicting goals. > >> Do you have suggestion on this? > > No, not any easy ones. Doing more of the uninit analysis early (there > is already an early > uninit pass) which would mean doing IPA analysis turing GCC into more > of a static analysis > tool. Theres the analyzer now, not sure if that can employ an early > LTO phase for example. > > Richard.