predicate aware uninitialized variable analysis
Xinliang David Li
davidxl@google.com
Thu Apr 22 01:12:00 GMT 2010
On Wed, Apr 14, 2010 at 3:44 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Tue, Apr 13, 2010 at 9:23 PM, Xinliang David Li <davidxl@google.com> wrote:
>> The patch did not make into 4.5. Try it again for 4.6.
>>
>> There are new changes since the last attempt: The candidate list of
>> PHIs (which may produce undefined values) are not precomputed. In the
>> new patch, the predicate check will also be done on uses by phi
>> arguments. Only when the uses in the phi arguments are not protected
>> properly by a predicate, the phi statement will then be added to the
>> worklist (and uses of its definitions will be checked later).
>>
>> Bootstrap and tested on x86_64/linux, and lots of apps.
>
> Can you instead of returning a sbitmap from compute_uninit_opnds_pos
> use an unsigned int mask (with proper checks for PHIs with too many
> operands which you don't want to handle because of complexity
> reasons anyway)?
>
Done. Did not bother to check when there are more operands that can be handled.
> + bool is_postdom = false;
> +
> + is_postdom = dominated_by_p (CDI_POST_DOMINATORS, bb2, bb1);
> +
> + if (!is_postdom)
> + return false;
>
> save us code and simply write
>
> if (!dominated_by_p (CDI_POST_DOMINATORS, bb2, bb1))
> return false;
>
Done.
> You do compute control-dependences of some sort - can this
> code be shared with the control-dependence computation in
> tree-ssa-dce.c? Thus, can you re-use that instead? There's
> the same find_pdom stuff you have as well.
This is slightly different -- the one in this patch does control
dependence computation on demand for bb of interests, which is more
suitable.
>
> is_value_included_in looks like it should use code from tree-vrp.c.
>
Right, ideally the code should be shared. However there is no direct
code that can be shared in the current implementation -- the code in
value_inside_range is minimal, the majority of the code would be
converting the range in uninit check to value_range_t form which still
need to be written.
However, it may be worth to refactor vrp code to be some common
utility functions some day -- probably not in this patch.
> It's always a good opportunity to separate and abstract out code
> we can use from multiple places instead of re-inventing the
> wheel over and over.
Agree.
>
> find_matching_predicate_in_rest_chains also looks remotely
> similar to what tree-ssa-loop-niter.c:simplify_using_initial_conditions
> does.
Similar to the vrp case -- some refactoring is needed before sharing can happen.
>
> The pass is rather large, so I appreciate some review from other
> folks (I do believe it should try to use/enhance existing functionality).
>
Diego has done it internally.
> Btw, thanks for the large collection of testcases. Can you check
> which uninitialized vars bugs this fixes and add them to the
> changelog entry?
>
Have checked some bug reports. Will update the change log when submitting it.
Ok for check in?
Thanks,
David
> Richard.
>
>
>> Ok for 4.6?
>>
>> David
>>
>>
>>
>> On Wed, Jul 22, 2009 at 2:19 PM, Xinliang David Li <davidxl@google.com> wrote:
>>> Hi, this was a unsubmitted patch from last year. The patch implements
>>> predicate aware uninitialized variable warning in GCC. The
>>> implementation changed the way potentially uninitialized variables are
>>> warned as of today. Before the change, GCC gave a warning when an
>>> empty def is used by an phi operand. This is not only noisy, but also
>>> does not have precise source information on where the uninit reference
>>> is. After the change, the warning is only given on actual uses of phi
>>> defs that are potentially undefined (with empty operands or possibly
>>> empty operands -- defined transitively). In the analysis, The
>>> predicate guarding the use of potentially uninitialized variable is
>>> compared against the predicate guarding the definition. The predicate
>>> expressions are formed using both control dependence and data
>>> dependence information. Some notes:
>>>
>>> 1. In current GCC, many of the false positives can be eliminated if
>>> jump threading kicks in, but slightly more complicated cases (as in
>>> the examples and test cases attached) will defeat it.
>>> 2. The predicate expression comparison/evaluation in the
>>> implementation does/can not rely on expr tree simplification/folding
>>> to do the job, and is a little rusty -- but good enough for the
>>> applications tested (and test cases accumulated).
>>> 3. Diego has spent lot of time reviewing the code last year.
>>> 4. bootstrap and tested on i686/linux. SPEC06/SPEC2k/internal apps.
>>>
>>> Let me know if this ok enough for mainline. If not, I will create a
>>> public branch and whoever is interested in enhancing the analysis can
>>> start contributing.
>>>
>>> Thanks,
>>>
>>> David
>>>
>>> ==============================================================
>>>
>>> The following are some examples. For more, take a look at the test
>>> cases included in the patch file.
>>>
>>>
>>> Example 1:
>>> ======================
>>>
>>> int g;
>>> void bar (void);
>>> void blah (int);
>>>
>>> int foo (int n, int m, int r)
>>> {
>>> int flag = 0;
>>> int v;
>>>
>>> if (n)
>>> {
>>> v = r;
>>> flag = 1;
>>> }
>>>
>>> if (m)
>>> g++;
>>> else
>>> bar();
>>>
>>> if (flag)
>>> blah(v); /* { dg-bogus "uninitialized" "bogus uninitialized var
>>> warning" } */
>>>
>>> return 0;
>>> }
>>>
>>>
>>>
>>> // Example 2 (flag check after inlining -- very common scenario)
>>> ==================================================================
>>>
>>> typedef long long int64;
>>> void incr ();
>>> bool is_valid (int);
>>> int get_time ();
>>>
>>> class A
>>> {
>>> public:
>>> A ();
>>> ~A () {
>>> if (I) delete I;
>>> }
>>>
>>> private:
>>> int* I;
>>> };
>>>
>>> bool get_url (A *);
>>>
>>> class M {
>>>
>>> public:
>>> __attribute__ ((always_inline)) int GetC (int *c) {
>>>
>>> A details_str;
>>> if (!get_url (&details_str))
>>> {
>>> incr ();
>>> return 1;
>>> }
>>>
>>> *c = get_time ();
>>> return -1;
>>> }
>>>
>>> void do_sth();
>>> void do_sth2();
>>>
>>> void P (int64 t)
>>> {
>>> int cc; /* { dg-bogus "uninitialized" "uninitialized variable
>>> warning" } */
>>> if (GetC (&cc) >= 0 )
>>> return;
>>>
>>> if (t && cc <= 0 ) /* { dg-bogus "uninitialized" "uninitialized
>>> variable warning" } */
>>> {
>>> this->do_sth();
>>> return;
>>> }
>>>
>>> do_sth2();
>>> }
>>> };
>>>
>>> M* m;
>>> void foo(int x)
>>> {
>>> m = new M;
>>> m->P(x);
>>> }
>>>
>>> // Example 3
>>> ========================
>>> int g;
>>> void bar();
>>> void blah(int);
>>>
>>> int foo (int n, int l, int m, int r)
>>> {
>>> int v;
>>>
>>> if (n > 10)
>>> v = r;
>>>
>>> if (m) g++;
>>> else bar();
>>>
>>> if ( (n > 10) && (l < 100))
>>> blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */
>>>
>>> if ( n > 100 )
>>> blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */
>>>
>>> return 0;
>>> }
>>>
>>> int foo_2 (int n, int l, int m, int r)
>>> {
>>> int v;
>>>
>>> if (n > 10)
>>> v = r;
>>>
>>> if (m) g++;
>>> else bar();
>>>
>>> if ( n < 10)
>>> blah (v); /* { dg-warning "uninitialized" "warning" } */
>>>
>>>
>>> return 0;
>>> }
>>>
>>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pred_uninit_r3.p
Type: text/x-pascal
Size: 90444 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20100422/f784b827/attachment.bin>
More information about the Gcc-patches
mailing list